Skip to content

Commit

Permalink
Restrict function and ADT definitions to the toplevel and refactor
Browse files Browse the repository at this point in the history
polymorphism
Closures can still be defined anywhere inside a toplevel function. Allows polymorphic functions that can do mutual recursion, and will make
it easier to implement modules later.
  • Loading branch information
andy-byers committed Aug 5, 2024
1 parent ee109bc commit 5c36d6a
Show file tree
Hide file tree
Showing 35 changed files with 2,553 additions and 3,071 deletions.
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ target_sources(paw
${PAW_SOURCE_DIR}/os.h
${PAW_SOURCE_DIR}/parse.h
${PAW_SOURCE_DIR}/prefix.h
${PAW_SOURCE_DIR}/resolve.h
${PAW_SOURCE_DIR}/rt.h
${PAW_SOURCE_DIR}/str.h
${PAW_SOURCE_DIR}/type.h
Expand Down
63 changes: 37 additions & 26 deletions GRAMMER.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,42 @@
** just don't emit unreachable code**
** use a tool to validate this...**

## Module
```ebnf
Module = "mod" name {Item} .
```

## Items
An item defined in a given module can be accessed from anywhere in the module.
Items must be placed at the toplevel, and are fixed at compile time.
```ebnf
Item = ["pub"] ItemDecl .
ItemDecl = ConstDecl | FunctionDecl | StructDecl |
EnumDecl | TypeDecl .
```

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

### Structures
```ebnf
StructDecl = "struct" name [Generics] StructBody .
StructBody = "{" {Field [";"]} "}" .
```

### Enumerations
```ebnf
EnumDecl = "enum" name [Generics] EnumBody .
EnumBody = "{" [{Variant ","} Variant] "}" .
Variant = name [Payload] .
Payload = "(" {Type ","} Type ")" .
```

## Statements
```ebnf
Stmt = ExprStmt | WhileStmt | DoWhileStmt |
Expand Down Expand Up @@ -33,8 +69,6 @@ MatchArm = Expr | Block .
```

## Paths
TODO: 'Suffixed expressions' can be split up into a path, possibly followed by a '.', '?', '(', or '{'.
TODO: The suffix after the path cannot contain '::', since any of the aformentioned tokens resolve to a value, as opposed to a type
```ebnf
Path = {Segment "::"} Segment .
Segment = name [TypeArgs] .
Expand All @@ -56,35 +90,12 @@ PathPat = Path .

## Declarations
```ebnf
Declaration = VarDecl | FunctionDecl | StructDecl |
EnumDecl | TypeDecl .
Declaration = VarDecl | TypeDecl .
VarDecl = "let" name [":" Type] "=" Expr .
TypeDecl = "type" name [Generics] "=" Type .
Generics = "<" {name ","} name [","] ">" .
```

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

### Structures
```ebnf
StructDecl = "struct" name [Generics] StructBody .
StructBody = "{" {Field [";"]} "}" .
```

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

## Operators
```ebnf
BinOp = "+" | "-" | "*" | "/" |
Expand Down
22 changes: 12 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ let b = 1 as bool
let i = 2 + 3.4 as int
struct Object {
value: int
value: int,
}
// all fields must be initialized
let obj = Object{value: 42}
Expand Down Expand Up @@ -112,15 +112,12 @@ let run_fib = || -> int {
### Structures
```
struct Object {
a: int
b: string
a: int,
b: string,
}
// all fields must be initialized
let o = Object{
a: 1,
b: 'two',
}
let o = Object{b: 'two', a: 1}
```

### Enumerations
Expand Down Expand Up @@ -148,7 +145,10 @@ if i == 0 {
// Null chaining operator: return immediately (with None/Err) if the operand is None/Err
// (must appear in a function that returns Option<T>/Result<T, E>), otherwise, unwraps
// the Option/Result
let v = maybe_none()?.field
fn maybe() -> Option<int> {
let i = maybe_none()?
return fallible(i)
}
// 'break'/'continue' (must appear in a loop):
break
Expand Down Expand Up @@ -208,8 +208,8 @@ assert(vec == [0, 1, 2])
// struct template
struct Object<S, T> {
a: S
b: T
a: S,
b: T,
}
// explicit instantiation uses 'turbofish'
Expand Down Expand Up @@ -327,6 +327,8 @@ assert(status != 0)

## Known problems
+ The C API has pretty much 0 type safety
+ Stenciler/monomorphization only works by accident
+ Closures allow captures from anywhere
+ Compiler will allow functions that don't return a value in all code paths
+ Likely requires a CFG and some data flow analysis: it would be very difficult to get right otherwise
+ It isn't possible to create an empty vector or map of a specific known type without creating a temporary: `let vec: [int] = []`
Expand Down
13 changes: 13 additions & 0 deletions src/api.c
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,19 @@ void paw_close(paw_Env *P)
P->alloc(P->ud, P, sizeof *P, 0);
}

int paw_find_public(paw_Env *P)
{
const String *name = v_string(P->top.p[-1]);
const int g = pawE_find_global(P, name);
paw_pop(P, 1);
return g;
}

void paw_push_public(paw_Env *P, int id)
{
pawR_read_global(P, id);
}

void paw_push_value(paw_Env *P, int index)
{
const Value v = *access(P, index);
Expand Down
Loading

0 comments on commit 5c36d6a

Please sign in to comment.