Skip to content

Commit

Permalink
Adds basic parametric polymorphism for functions and structures
Browse files Browse the repository at this point in the history
At this point, variables with generic types must be treated completely
generically. This will allow abstract data types, like 'Vec' and 'Map',
but doesn't allow creating, for example, a polymorphic function that
sums a list of numbers (either 'int' or 'float'). That behavior will be
implemented later, when the codebase becomes stable. Also using the
Boehm–Demers–Weiser garbage collector for now (using FetchContent from an unofficial git repo). At some point, paw will
get its own garbage collector. At first, it will be a simple tracing GC,
like the one we had before static typing was added, except that it needs
to coordinate with a custom allocator so it can find pointers (or
maintain a lookup table).
  • Loading branch information
andy-byers committed Jun 23, 2024
1 parent f0a7ca9 commit 417d8b5
Show file tree
Hide file tree
Showing 49 changed files with 8,234 additions and 4,574 deletions.
16 changes: 13 additions & 3 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -31,19 +31,26 @@ else()
INTERFACE m)
endif()

include(FetchContent)
FetchContent_Declare(gc
GIT_REPOSITORY https://github.com/ivmai/bdwgc.git
GIT_TAG v8.2.6)
FetchContent_MakeAvailable(gc)

set(PAW_SOURCE_DIR ${PROJECT_SOURCE_DIR}/src)

add_library(paw STATIC)
target_sources(paw
PUBLIC ${PAW_SOURCE_DIR}/api.h
${PAW_SOURCE_DIR}/ast.h
${PAW_SOURCE_DIR}/auxlib.h
${PAW_SOURCE_DIR}/array.h
${PAW_SOURCE_DIR}/bigint.h
${PAW_SOURCE_DIR}/call.h
${PAW_SOURCE_DIR}/code.h
${PAW_SOURCE_DIR}/debug.h
${PAW_SOURCE_DIR}/env.h
${PAW_SOURCE_DIR}/gc.h
${PAW_SOURCE_DIR}/gc_aux.h
${PAW_SOURCE_DIR}/lex.h
${PAW_SOURCE_DIR}/lib.h
${PAW_SOURCE_DIR}/map.h
Expand All @@ -59,6 +66,7 @@ target_sources(paw
${PAW_SOURCE_DIR}/util.h
${PAW_SOURCE_DIR}/value.h
PRIVATE ${PAW_SOURCE_DIR}/api.c
${PAW_SOURCE_DIR}/ast.c
${PAW_SOURCE_DIR}/auxlib.c
${PAW_SOURCE_DIR}/array.c
${PAW_SOURCE_DIR}/bigint.c
Expand All @@ -68,7 +76,7 @@ target_sources(paw
${PAW_SOURCE_DIR}/codegen.c
${PAW_SOURCE_DIR}/debug.c
${PAW_SOURCE_DIR}/env.c
${PAW_SOURCE_DIR}/gc.c
${PAW_SOURCE_DIR}/gc_aux.c
#${PAW_SOURCE_DIR}/iolib.c
${PAW_SOURCE_DIR}/lex.c
${PAW_SOURCE_DIR}/lib.c
Expand All @@ -82,10 +90,12 @@ target_sources(paw
${PAW_SOURCE_DIR}/rt.c
${PAW_SOURCE_DIR}/str.c
${PAW_SOURCE_DIR}/type.c
${PAW_SOURCE_DIR}/unify.c
${PAW_SOURCE_DIR}/util.c
${PAW_SOURCE_DIR}/value.c)
target_link_libraries(paw
PRIVATE paw_context)
PRIVATE paw_context
PUBLIC gc)
target_include_directories(paw
PUBLIC ${PAW_SOURCE_DIR})
target_compile_definitions(paw
Expand Down
148 changes: 148 additions & 0 deletions GRAMMER.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
# Paw language grammer (EBNF)
**TODO: get rid of requirement that "break" | "return" | "continue" is the last statement in the block**
** just don't emit unreachable code**
** use a tool to validate this...**

## Statements
```
Stmt ::= ExprStmt | WhileLoop | DoWhileLoop |
ForLoop | IfElse | Declaration |
Block .
Chunk ::= {Stmt [";"]} [LastStmt [";"]] .
Block ::= "{" Chunk "}" .
LastStmt ::= "return" [Expr] | "continue" | "break" .
ExprStmt ::= Operand "=" Expr | Call | Match .
```

### Control flow
```
IfElse ::= "if" Expr Block [{"else" IfElse} | "else" Block] .
WhileLoop ::= "while" Expr Block .
DoWhileLoop ::= "do" Block "while" Expr .
ForLoop ::= ForIn | ForNum .
ForIn ::= "for" name "in" Expr Block .
ForNum ::= "for" name "=" Expr "," Expr ["," Expr] Block .
Match ::= "match" Expr MatchBody .
MatchBody ::= "{" {MatchArm ","} MatchArm "}" .
MatchClause ::= Expr "=>" MatchArm .
MatchArm ::= Expr | Block .
```

## Declarations
```
Declaration ::= VarDecl | FunctionDecl |
ClassDecl | EnumDecl | TypeDecl .
VarDecl ::= "let" name [":" Type] "=" Expr .
TypeDecl ::= "type" name [TypeParam] "=" Type .
TypeParam ::= "[" {name ","} name "]" .
```

### Functions
```
FunctionDecl ::= "fn" Function .
Function ::= name [TypeParam] FuncType Block .
FuncType ::= "(" [{Field ","} Field] ")" ["->" Type] .
Field ::= name ":" Type .
```

### Classes
```
ClassDecl ::= "class" ClassType .
ClassType ::= name [TypeParam] ClassBody .
ClassBody ::= "{" {Attribute [";"]} "}" .
Attribute ::= Method | Field .
Method ::= ["static"] Function .
```

### Enumerators
```
EnumDecl ::= "enum" name EnumBody .
EnumBody ::= "{" [{Variant ","} Variant] "}" .
Variant ::= name [Payload] .
Payload ::= "(" {Type ","} Type ")" .
```

## Operators
```
BinOp ::= "+" | "-" | "*" | "/" |
"%" | "&" | "^" | "|" |
"<" | "<=" | ">" | ">=" |
"==" | "!=" | "&&" | "||" .
UnOp ::= "-" | "~" | "!" | "#" .
```

## Expressions
```
Expr ::= PrimaryExpr | Expr BinOp Expr | UnOp Expr .
PrimaryExpr ::= Operand | Call | Literal | "(" Expr ")" .
Call ::= PrimaryExpr "(" [ExprList] ")" .
Operand ::= name | Index | Selector .
Index ::= PrimaryExpr "[" ExprList "]" .
Selector ::= PrimaryExpr "." name .
ExprList ::= {Expr ","} Expr .
```

## Types
```
Type ::= name [TypeArgs] | TypeLit .
TypeLit ::= FuncType | ArrayType | TupleType .
FuncType ::= "fn" "(" [TypeList] ")" ["->" Type] .
TypeList ::= {Type ","} Type
TypeArgs ::= "[" TypeList "]" .
NamedType ::= name [TypeArgs] .
ArrayType ::= "[" Type ";" int_lit "]" .
TupleType ::= "(" [Type "," [Type]] ")" .
```

## Operands
```
Operand ::= Literal | name [TypeArgs] .
Literal ::= BasicLit | CompositeLit .
BasicLit ::= int_lit | bool_lit | float_lit | string_lit .
```

### Composite literals
Note that the unit type is just a 0-tuple (an tuple with 0 elements).
A 1-tuple must have a trailing `,` to distinguish it from a parenthesized expression.
```
CompositeLit ::= ClassLit | ArrayLit | TupleLit | VariantLit .
ClassLit ::= NamedType "{" [ItemList [","]] "}" .
ArrayLit ::= "[" [ExprList [","]] "]" .
TupleLit ::= "(" [Expr "," [Expr [","]]] ")" .
VariantLit ::= name ["(" {Expr ","} Expr ")"] .
ItemList ::= KeyedItem {"," KeyedItem} [","] .
KeyedItem ::= [Key ":"] Expr .
Key ::= name | Expr .
```

### Integer literals
```
int_lit ::= decimal_lit | binary_lit | octal_lit | hex_lit .
decimal_lit ::= "0" | ("1" … "9") [decimal_digits] .
binary_lit ::= "0" ("b" | "B") binary_digits .
octal_lit ::= "0" ("o" | "O") octal_digits .
hex_lit ::= "0" ("x" | "X") hex_digits .
```

### Float literals
```
float_lit := decimal_digits "." [decimal_digits] [decimal_exponent] |
decimal_digits decimal_exponent |
"." decimal_digits [decimal_exponent] .
decimal_exponent := ("e" | "E") ["+" | "-"] decimal_digits .
```

## Miscellaneous
```
name ::= letter {letter | decimal_digit} .
letter ::= "A" … "Z" | "a" … "z" | "_" .
decimal_digit ::= "0" … "9" .
binary_digit ::= "0" | "1" .
octal_digit ::= "0" … "7" .
hex_digit ::= "0" … "9" | "A" … "F" | "a" … "f" .
decimal_digits ::= decimal_digit {decimal_digit} .
binary_digits ::= binary_digit {binary_digit} .
octal_digits ::= octal_digit {octal_digit} .
hex_digits ::= hex_digit {hex_digit} .
```

Loading

0 comments on commit 417d8b5

Please sign in to comment.