Skip to content

Commit

Permalink
Fix container for loops and some tests
Browse files Browse the repository at this point in the history
  • Loading branch information
andy-byers committed Jul 21, 2024
1 parent 416774f commit 7a2b667
Show file tree
Hide file tree
Showing 45 changed files with 1,355 additions and 1,242 deletions.
2 changes: 1 addition & 1 deletion .clang-format
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ BasedOnStyle: LLVM

AccessModifierOffset: -4
BreakBeforeBraces: Linux
ColumnLimit: 80
ColumnLimit: 0
IndentCaseLabels: true
IndentWidth: 4
SpaceBeforeCaseColon: false
Expand Down
26 changes: 17 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,11 @@ fn fib(n: int) -> int {
return fib(n - 2) + fib(n - 1)
}
fib(10)
// use closure syntax to capture variables
let run_fib = || -> int {
return fib(5)
}
```

### Structures
Expand Down Expand Up @@ -145,7 +150,7 @@ break
continue
// Numeric 'for' loop:
for i in 0, 10, 2 { // start, end[, step]
for i = 0, 10, 2 { // start, end[, step]
}
Expand Down Expand Up @@ -182,7 +187,7 @@ Variables with generic types must be treated generically, that is, they can only
This allows each template to be type checked a single time, rather than once for each unique instantiation, and makes it easier to generate meaningful error messages.
```
fn map<A, B>(f: fn(A) -> B, vec: [A]) -> [B] {
let result: [B] = []
let result = []
for a in vec {
result.push(f(a))
}
Expand Down Expand Up @@ -233,16 +238,16 @@ let c = triplet.2
```
let empty: [int] = []
// infer T = string
let empty = []
empty.push('a')
empty.push('a')
let vec = [
[[1, 2, 3], [0]],
[[4, 5, 6], [1]],
[[7, 8, 9], [2]],
]
// infer T = int
let vec = [1, 2, 3]
assert(vec[:1] == [1])
assert(vec[1:-1] == [2])
Expand All @@ -253,10 +258,10 @@ assert(vec[-1:] == [3])
```
let empty: [int: string] = [:]
// infer K = int, V = string
let empty = [:]
empty[0] = 'abc'
// infer K = int, V = string
let map = [1: 'a', 2: 'b']
map[3] = 42
map.erase(1)
Expand Down Expand Up @@ -296,24 +301,27 @@ assert(status != 0)
|1 |`=` |Assignment |Right |

## Roadmap
+ [x] static typing
+ [x] static, string typing
+ [x] special-cased builtin containers (`[T]` and `[K: V]`)
+ [x] type inference for structure templates (including builtin containers)
+ [ ] type inference for enumeration templates
+ [x] type inference for `struct` templates and builtin containers
+ [ ] methods using `impl` blocks
+ [ ] module system and `import` keyword
+ [ ] type inference for `enum` templates
+ [ ] pattern matching (`switch` construct)
+ [ ] pattern matching (`if let`, `let` bindings)
+ [ ] constness (`var` vs `let`)
+ [ ] split `string` into `str` and `String`, where `str` is a byte array and `String` is always valid UTF-8
+ [x] sum types/discriminated unions (`enum`)
+ [x] product types (tuple)
+ [ ] compiler optimization passes
+ [ ] custom garbage collector (using Boehm GC for now)
+ [ ] methods
+ [ ] metamethods
+ [ ] generic constraints/bounds
+ [ ] associated types on `struct`s (`A::B`)
+ [ ] existential types

## Known problems
+ The C API has pretty much 0 type safety
+ 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
183 changes: 63 additions & 120 deletions src/api.c
Original file line number Diff line number Diff line change
Expand Up @@ -93,83 +93,6 @@ void paw_close(paw_Env *P)
P->alloc(P->ud, P, sizeof *P, 0);
}

paw_Bool paw_is_bool(paw_Env *P, int index)
{
return paw_type(P, index) == PAW_TBOOL;
}

paw_Bool paw_is_int(paw_Env *P, int index)
{
return paw_type(P, index) == PAW_TINT;
}

paw_Bool paw_is_float(paw_Env *P, int index)
{
return paw_type(P, index) == PAW_TFLOAT;
}

paw_Bool paw_is_string(paw_Env *P, int index)
{
return paw_type(P, index) == PAW_TSTRING;
}

paw_Bool paw_is_function(paw_Env *P, int index)
{
return paw_type(P, index) == PAW_TFUNCTION;
}

paw_Bool paw_is_tuple(paw_Env *P, int index)
{
return paw_type(P, index) == PAW_TTUPLE;
}

paw_Bool paw_is_struct(paw_Env *P, int index)
{
return paw_type(P, index) == PAW_TSTRUCT;
}

paw_Bool paw_is_foreign(paw_Env *P, int index)
{
return paw_type(P, index) == PAW_TFOREIGN;
}

int paw_type(paw_Env *P, int index)
{
const Value v = *access(P, index);
return 0;
// switch (v_type(v)) {
// case VNULL:
// return PAW_NULL;
// case VTRUE:
// case VFALSE:
// return PAW_TBOOL;
// case VCLOSURE:
// case VMETHOD:
// case VNATIVE:
// return PAW_TFUNCTION;
// case VSTRING:
// return PAW_TSTRING;
// case VARRAY:
// return PAW_TARRAY;
// case VMAP:
// return PAW_TMAP;
// case VSTRUCT:
// return PAW_TSTRUCT;
// case VBIGINT:
// case VNUMBER:
// return PAW_TINT;
// case VFOREIGN:
// return PAW_TFOREIGN;
// default:
// return PAW_TFLOAT;
// }
}

const char *paw_typename(paw_Env *P, int index)
{
return api_typename(paw_type(P, index));
}

void paw_push_value(paw_Env *P, int index)
{
const Value v = *access(P, index);
Expand All @@ -183,11 +106,20 @@ void paw_push_unit(paw_Env *P, int n)
}
}

void paw_push_boolean(paw_Env *P, paw_Bool b) { pawC_pushb(P, b); }
void paw_push_boolean(paw_Env *P, paw_Bool b)
{
pawC_pushb(P, b);
}

void paw_push_float(paw_Env *P, paw_Float f) { pawC_pushf(P, f); }
void paw_push_float(paw_Env *P, paw_Float f)
{
pawC_pushf(P, f);
}

void paw_push_int(paw_Env *P, paw_Int i) { pawC_pushi(P, i); }
void paw_push_int(paw_Env *P, paw_Int i)
{
pawC_pushi(P, i);
}

void paw_push_native(paw_Env *P, paw_Function fn, int n)
{
Expand Down Expand Up @@ -234,9 +166,15 @@ const char *paw_push_fstring(paw_Env *P, const char *fmt, ...)
return s;
}

paw_Bool paw_bool(paw_Env *P, int index) { return v_true(*access(P, index)); }
paw_Bool paw_bool(paw_Env *P, int index)
{
return v_true(*access(P, index));
}

paw_Int paw_int(paw_Env *P, int index) { return v_int(*access(P, index)); }
paw_Int paw_int(paw_Env *P, int index)
{
return v_int(*access(P, index));
}

paw_Float paw_float(paw_Env *P, int index)
{
Expand Down Expand Up @@ -360,7 +298,10 @@ int paw_call(paw_Env *P, int argc)
return status;
}

int paw_get_count(paw_Env *P) { return P->top.p - P->cf->base.p; }
int paw_get_count(paw_Env *P)
{
return P->top.p - P->cf->base.p;
}

static int upvalue_index(int nup, int index)
{
Expand All @@ -372,35 +313,33 @@ static int upvalue_index(int nup, int index)
return index;
}

// void paw_get_upvalue(paw_Env *P, int ifn, int index)
//{
// Value *pv = pawC_push0(P);
// const Value fn = *access(P, ifn);
// switch (v_type(fn)) {
// case VNATIVE: {
// Native *f = v_native(fn);
// *pv = f->up[upvalue_index(f->nup, index)];
// break;
// }
// case VCLOSURE: {
// Closure *f = v_closure(fn);
// UpValue *u = f->up[upvalue_index(f->nup, index)];
// *pv = *u->p.p;
// break;
// }
// default:
// pawR_error(P, PAW_ETYPE, "'%s' has no upvalues",
// api_typename(api_type(fn)));
// }
// }
//
// void paw_get_global(paw_Env *P, const char *name)
//{
// if (!paw_check_global(P, name)) {
// pawR_error(P, PAW_ENAME, "global '%s' does not exist", name);
// }
// }
//
void paw_get_upvalue(paw_Env *P, int ifn, int index)
{
Value *pv = pawC_push0(P);
const Value fn = *access(P, ifn);
switch (v_object(fn)->gc_kind) {
case VNATIVE: {
Native *f = v_native(fn);
*pv = f->up[upvalue_index(f->nup, index)];
break;
}
case VCLOSURE: {
Closure *f = v_closure(fn);
UpValue *u = f->up[upvalue_index(f->nup, index)];
*pv = *u->p.p;
break;
}
default:
pawR_error(P, PAW_ETYPE, "type has no upvalues");
}
}

void paw_get_global(paw_Env *P, int index)
{
GlobalVar *var = pawE_get_global(P, index);
pawC_pushv(P, var->value);
}

// paw_Bool paw_check_global(paw_Env *P, const char *name)
//{
// paw_push_string(P, name);
Expand Down Expand Up @@ -499,6 +438,8 @@ static int upvalue_index(int nup, int index)
//
void paw_set_global(paw_Env *P, const char *name)
{
paw_unused(P);
paw_unused(name);
// paw_push_string(P, name);
// paw_rotate(P, -2, 1); // Swap
//
Expand Down Expand Up @@ -531,6 +472,8 @@ void paw_set_global(paw_Env *P, const char *name)
//
void paw_create_array(paw_Env *P, int n)
{
paw_unused(P);
paw_unused(n);
// pawR_literal_array(P, n);
}
//
Expand Down Expand Up @@ -615,13 +558,13 @@ void paw_shift(paw_Env *P, int n)
paw_pop(P, n);
}

// void paw_call_global(paw_Env *P, const char *name, int argc)
//{
// paw_get_global(P, name);
// paw_insert(P, -argc - 2);
// paw_call(P, argc);
// }
//
void paw_call_global(paw_Env *P, int index, int argc)
{
paw_get_global(P, index);
paw_insert(P, -argc - 2);
paw_call(P, argc);
}

// void paw_call_attr(paw_Env *P, int index, const char *name, int argc)
//{
// paw_push_value(P, index);
Expand All @@ -644,6 +587,6 @@ void paw_raw_equals(paw_Env *P)
{
const Value x = P->top.p[-2];
const Value y = P->top.p[-1];
// paw_push_boolean(P, pawV_equal(x, y));
paw_push_boolean(P, x.u == y.u);
paw_shift(P, 2);
}
Loading

0 comments on commit 7a2b667

Please sign in to comment.