feat: align M3 slices and strings with v0.1.7

This commit is contained in:
2026-08-16 18:23:30 +09:00
parent cba2c86fbc
commit 42abc0d7e7
32 changed files with 183 additions and 60 deletions
+1 -1
View File
@@ -8,7 +8,7 @@ FeNode *fe_node(FeAst *a, FeNodeKind k, FeLoc loc, const char *text, unsigned lo
FeNode *n=(FeNode *)fe_arena_alloc(&a->arena,sizeof(FeNode));
if (!n) return 0;
n->kind=k; n->loc=loc; n->text=text?fe_arena_strdup(&a->arena,text,len):0;
n->a=n->b=n->c=n->children=n->next=0; n->cname=0; n->aux_text=0; n->aux_cname=0; n->sem_type=0; n->flags=0; return n;
n->a=n->b=n->c=n->children=n->next=0; n->cname=0; n->aux_text=0; n->aux_cname=0; n->sem_type=0; n->sem_decl=0; n->flags=0; return n;
}
void fe_node_add(FeNode *parent, FeNode *child)
{
+1
View File
@@ -30,6 +30,7 @@ struct FeNode {
char *aux_text;
char *aux_cname;
FeType *sem_type;
FeNode *sem_decl;
unsigned flags;
};
+37 -16
View File
@@ -54,7 +54,7 @@ static int is_copy_type(FeType *t)
unsigned i;
if (!t) return 1;
if (t->kind==FE_TYPE_OWNED) return 0;
if (t->kind==FE_TYPE_REF) return !t->ref_mut;
if (t->kind==FE_TYPE_REF || t->kind==FE_TYPE_SLICE) return !t->ref_mut;
if (t->kind==FE_TYPE_ARRAY) return is_copy_type(t->elem);
if (t->kind==FE_TYPE_STRUCT) {
if (t->has_drop) return 0;
@@ -311,6 +311,8 @@ static FeNode *find_const_node(FeCheck *c, const char *name)
return 0;
}
static int format_is_slice_u8(FeType *t);
static const char *builtin_format(FeCheckerState *s, FeNode *fmt)
{
FeNode *decl;
@@ -323,7 +325,7 @@ static const char *builtin_format(FeCheckerState *s, FeNode *fmt)
sym->decl : find_const_node(s->c,fmt->text);
if (decl && decl->b && decl->b->kind==FE_N_LITERAL &&
decl->b->text && decl->b->text[0]=='"') {
if (!decl->a || fe_type_from_ast(&s->c->types,decl->a)->kind==FE_TYPE_STR)
if (!decl->a || format_is_slice_u8(fe_type_from_ast(&s->c->types,decl->a)))
return decl->b->text;
}
}
@@ -347,10 +349,10 @@ static int format_arg_ok(FeType *t, int verb)
if (!t) return 0;
if (verb=='x') return fe_type_is_integer(t);
if (verb=='c') return t->kind==FE_TYPE_CHAR;
if (verb=='s') return t->kind==FE_TYPE_STR || format_is_slice_u8(t);
if (verb=='s') return format_is_slice_u8(t);
if (verb=='b') return t->kind==FE_TYPE_BOOL;
if (t->kind==FE_TYPE_INT || t->kind==FE_TYPE_BOOL ||
t->kind==FE_TYPE_CHAR || t->kind==FE_TYPE_STR) return 1;
t->kind==FE_TYPE_CHAR) return 1;
return format_is_slice_u8(t) ||
(t->kind==FE_TYPE_ENUM && t->is_error);
}
@@ -381,7 +383,8 @@ static void check_format_call(FeCheckerState *s, FeNode *n)
if (strcmp(n->text,"@sprint")==0) {
if (!fmt_node) { err(s->c,n->loc,"@sprint requires a buffer"); return; }
t=check_expr(s,fmt_node);
if (!format_is_slice_u8(t)) err(s->c,fmt_node->loc,"@sprint requires []u8 buffer");
if (!format_is_slice_u8(t) || !t->ref_mut)
err(s->c,fmt_node->loc,"@sprint requires []mut u8 buffer");
fmt_node=fmt_node->next;
}
fmt=builtin_format(s,fmt_node);
@@ -517,7 +520,18 @@ static FeType *check_index(FeCheckerState *s, FeNode *n)
if(n->c || !n->b) {
if (base->kind==FE_TYPE_ARRAY && !array_slice_lvalue(n->a))
err(s->c,n->loc,"array slicing requires a stable lvalue");
if(n->c) { idx=check_expr(s,n->c); if(known(idx)&&!fe_type_is_integer(idx)) err(s->c,n->loc,"slice bound must be an integer"); } elem=base->elem; n->sem_type=fe_type_slice(&s->c->types,elem); if(base->kind==FE_TYPE_STR) n->flags|=2U; return n->sem_type; }
if(n->c) {
idx=check_expr(s,n->c);
if(known(idx)&&!fe_type_is_integer(idx))
err(s->c,n->loc,"slice bound must be an integer");
}
elem=base->elem;
n->sem_type=(base->kind==FE_TYPE_SLICE ? base->ref_mut :
lvalue_writable(s,n->a)) ?
fe_type_mut_slice(&s->c->types,elem) :
fe_type_slice(&s->c->types,elem);
return n->sem_type;
}
n->sem_type=base->elem; return n->sem_type;
}
@@ -715,6 +729,7 @@ static FeType *check_expr(FeCheckerState *s, FeNode *n)
return unknown(c);
}
n->a->cname = sym->cname;
n->sem_decl = sym->fn;
if (!sym->fn) {
err(c, n->loc, "name is not a function");
return unknown(c);
@@ -725,7 +740,10 @@ static FeType *check_expr(FeCheckerState *s, FeNode *n)
a = check_expr(s, arg);
mark_moved(s,arg,a);
b = node_type(c, param->a);
if (!compatible(b, a, arg) && a->kind != FE_TYPE_UNKNOWN)
if (!compatible(b, a, arg) &&
!(b && a && b->kind==FE_TYPE_SLICE && a->kind==FE_TYPE_SLICE &&
!b->ref_mut && a->ref_mut && fe_type_equal(b->elem,a->elem)) &&
a->kind != FE_TYPE_UNKNOWN)
err(c, arg->loc, "argument type mismatch");
param = param->next;
arg = arg->next;
@@ -819,14 +837,15 @@ static FeType *check_lvalue(FeCheckerState *s, FeNode *n, int read)
n->sem_type=field->type; return field->type;
}
if (n && n->kind == FE_N_INDEX) {
if (n->a && n->a->sem_type && n->a->sem_type->kind == FE_TYPE_STR) {
err(s->c, n->loc, "str is immutable");
}
if (n->a && n->a->kind == FE_N_INDEX && (n->a->flags & 2U))
err(s->c, n->loc, "str slice is immutable");
if (!lvalue_writable(s,n->a))
err(s->c,n->loc,"cannot assign through immutable value");
base=check_index(s,n);
if (n->a && n->a->sem_type &&
n->a->sem_type->kind == FE_TYPE_SLICE &&
!n->a->sem_type->ref_mut)
err(s->c,n->loc,"cannot write through shared slice");
else if (n->a && n->a->sem_type &&
n->a->sem_type->kind != FE_TYPE_SLICE &&
!lvalue_writable(s,n->a))
err(s->c,n->loc,"cannot assign through immutable value");
return base;
}
if (n) err(s->c, n->loc, "assignment requires a variable");
@@ -903,8 +922,8 @@ static void check_for(FeCheckerState *s, FeNode *n)
else if (n->a && n->a->kind==FE_N_INDEX && n->a->a &&
n->a->a->kind==FE_N_IDENT)
iter_sym=find_symbol(s->scope,n->a->a->text ? n->a->a->text : "");
iter_mut=iter_sym && iter_sym->mutable;
if (start->kind==FE_TYPE_STR) iter_mut=0;
iter_mut=start->kind==FE_TYPE_SLICE ? start->ref_mut :
(iter_sym && iter_sym->mutable);
ref_type=fe_type_ref(&s->c->types,elem,iter_mut);
if (iter_mut) n->flags |= 4U;
s->scope=scope_new(s,old);
@@ -1017,6 +1036,8 @@ static void check_stmt(FeCheckerState *s, FeNode *n)
err(c, n->loc, "initializer type mismatch");
if (b->kind == FE_TYPE_VOID)
err(c, n->loc, "void expression cannot initialize a variable");
if (n->kind==FE_N_LET && a->kind==FE_TYPE_SLICE && a->ref_mut)
err(c,n->loc,"let cannot bind a mutable slice");
mark_moved(s,n->b,b);
add_symbol(s, s->scope, n->text, a, 0, 0, 1,
local_cname(c, n->text ? n->text : "local"), n);
+49 -19
View File
@@ -75,8 +75,10 @@ static void emit_one_type(FeEmitter *e, FeType *t)
} else if(t->kind==FE_TYPE_ARRAY) {
fputs(t->cname,e->out); fputs(" { ",e->out); fputs(fe_type_c_name(t->elem,e->pointer_bits),e->out); fputs(" a[",e->out); fprintf(e->out,"%lu",t->length); fputs("]; };\n",e->out);
} else if(t->kind==FE_TYPE_SLICE && t->cname) {
fputs("typedef struct { ",e->out); fputs(fe_type_c_name(t->elem,e->pointer_bits),e->out); fputs(" *p; unsigned long n; } ",e->out); fputs(t->cname,e->out); fputs(";\n",e->out);
fprintf(e->out,"static %s %s(%s *p, unsigned long n) { %s s; s.p=p; s.n=n; return s; }\n",t->cname,t->maker,fe_type_c_name(t->elem,e->pointer_bits),t->cname);
fputs("typedef struct { ",e->out);
if(!t->ref_mut) fputs("const ",e->out);
fputs(fe_type_c_name(t->elem,e->pointer_bits),e->out); fputs(" *p; unsigned long n; } ",e->out); fputs(t->cname,e->out); fputs(";\n",e->out);
fprintf(e->out,"static %s %s(%s%s *p, unsigned long n) { %s s; s.p=p; s.n=n; return s; }\n",t->cname,t->maker,t->ref_mut ? "" : "const ",fe_type_c_name(t->elem,e->pointer_bits),t->cname);
} else if(t->kind==FE_TYPE_ERROR_UNION) {
fputs(t->cname,e->out); fputs(" { unsigned short e; ",e->out);
fputs(fe_type_c_name(t->error_value,e->pointer_bits),e->out);
@@ -97,8 +99,6 @@ static void emit_one_type(FeEmitter *e, FeType *t)
static void emit_type_defs(FeEmitter *e)
{
FeType *t;
fputs("typedef struct { const unsigned char *p; unsigned long n; } fe_str;\n",e->out);
fputs("static fe_str fe_make_str(const unsigned char *p, unsigned long n) { fe_str s; s.p=p; s.n=n; return s; }\n",e->out);
/* Every fixed array has a slice conversion helper, even if this unit
only indexes the array. Intern those result types before emission so
their typedefs are present before helper definitions. */
@@ -246,14 +246,6 @@ static void emit_type_helpers(FeEmitter *e)
fprintf(e->out,"static %s %s(%s x, unsigned long a) { return %s(x,a,x.n); }\n",t->cname,t->tail_slicer,t->cname,t->slicer);
}
}
fputs("static unsigned char fe_idx_str(fe_str x, unsigned long i) { ",e->out);
if(!e->no_checks) fputs("if (i >= x.n) fe_trap_bounds(); ",e->out);
fputs("return x.p[i]; }\n",e->out);
fputs("static fe_str fe_slice_str(fe_str x, unsigned long a, unsigned long b) { ",e->out);
if(!e->no_checks) fputs("if (a > b || b > x.n) fe_trap_bounds(); ",e->out);
fputs("return fe_make_str(x.p+a,b-a); }\n",e->out);
fputs("static fe_str fe_full_slice_str(fe_str x) { return fe_slice_str(x,0,x.n); }\n",e->out);
fputs("static fe_str fe_tail_slice_str(fe_str x, unsigned long a) { return fe_slice_str(x,a,x.n); }\n",e->out);
}
static void emit_m4_runtime(FeEmitter *e)
@@ -276,7 +268,6 @@ static void emit_m4_runtime(FeEmitter *e)
fputs("unsigned long fe_m4_sprint_finish(void) { unsigned long result; if (!fe_m4_sprint_depth) abort(); --fe_m4_sprint_depth; result=fe_m4_sprint_stack[fe_m4_sprint_depth].start_n-fe_m4_sprint_stack[fe_m4_sprint_depth].b.n; return result; }\n",e->out);
fputs("unsigned short fe_m4_write_bytes(fe_writer w, const unsigned char *p, unsigned long n) { return w.write_fn ? w.write_fn(w.ctx,p,n) : 1; }\n",e->out);
fputs("unsigned short fe_m4_write_cstr(fe_writer w, const char *p) { return fe_m4_write_bytes(w,(const unsigned char*)p,(unsigned long)strlen(p)); }\n",e->out);
fputs("unsigned short fe_m4_write_str(fe_writer w, fe_str s) { return fe_m4_write_bytes(w,s.p,s.n); }\n",e->out);
fputs("#define fe_m4_write_slice(w,s) fe_m4_write_bytes((w),(s).p,(s).n)\n",e->out);
fputs("unsigned short fe_m4_write_int(fe_writer w, long v) { char b[40]; sprintf(b,\"%ld\",v); return fe_m4_write_cstr(w,b); }\n",e->out);
fputs("unsigned short fe_m4_write_hex(fe_writer w, unsigned long v) { char b[40]; sprintf(b,\"%lx\",v); return fe_m4_write_cstr(w,b); }\n",e->out);
@@ -504,9 +495,8 @@ static void emit_m4_arg(FeEmitter *e, FeNode *arg, int verb,
if (verb=='b') {
fputs("fe_m4_write_bool(",e->out); emit_m4_writer_value(e,writer,buffer); fputs(", ",e->out); emit_expr(e,arg); fputc(')',e->out); return;
}
if (verb=='s' || (verb==' ' && t && (t->kind==FE_TYPE_STR || t->kind==FE_TYPE_SLICE))) {
if (t && t->kind==FE_TYPE_STR) fputs("fe_m4_write_str(",e->out);
else fputs("fe_m4_write_slice(",e->out);
if (verb=='s' || (verb==' ' && t && t->kind==FE_TYPE_SLICE)) {
fputs("fe_m4_write_slice(",e->out);
emit_m4_writer_value(e,writer,buffer); fputs(", ",e->out); emit_expr(e,arg); fputc(')',e->out); return;
}
if (error_value) {
@@ -651,7 +641,29 @@ static FeNode *init_field(FeNode *n, const char *name)
static void emit_slice_call(FeEmitter *e, FeNode *n)
{
FeType *bt=n->a ? n->a->sem_type : 0;
const char *maker=bt && bt->slicer ? bt->slicer : "fe_slice_str";
const char *maker=n->sem_type && n->sem_type->maker ? n->sem_type->maker :
(bt && bt->slicer ? bt->slicer : "fe_missing_slice");
if (bt && (bt->kind==FE_TYPE_ARRAY || bt->kind==FE_TYPE_SLICE)) {
fputs(n->sem_type && n->sem_type->slicer ?
n->sem_type->slicer : "fe_missing_slicer",e->out);
fputc('(',e->out); fputs(maker,e->out); fputc('(',e->out);
if (bt->kind==FE_TYPE_ARRAY) {
fputs("(&",e->out); emit_lvalue(e,n->a); fputs(")->a",e->out);
} else {
emit_expr(e,n->a); fputs(".p",e->out);
}
fputs(", ",e->out);
if(bt->kind==FE_TYPE_ARRAY) fprintf(e->out,"%lu",bt->length);
else { emit_expr(e,n->a); fputs(".n",e->out); }
fputs("), ",e->out);
if(n->b) emit_expr(e,n->b); else fputs("0",e->out);
fputs(", ",e->out);
if(n->c) emit_expr(e,n->c);
else if(bt->kind==FE_TYPE_ARRAY) fprintf(e->out,"%lu",bt->length);
else { emit_expr(e,n->a); fputs(".n",e->out); }
fputc(')',e->out);
return;
}
if (!n->b && !n->c && bt && bt->full_slicer) {
fputs(bt->full_slicer,e->out);
if (bt->kind==FE_TYPE_ARRAY) { fputs("(&",e->out); emit_lvalue(e,n->a); }
@@ -698,7 +710,13 @@ static void emit_expr(FeEmitter *e, FeNode *n)
case FE_N_LITERAL:
if (n->text && strcmp(n->text, "true") == 0) fputs("1", e->out);
else if (n->text && strcmp(n->text, "false") == 0) fputs("0", e->out);
else if (n->text && n->text[0]=='"') { fputs("fe_make_str((const unsigned char*)",e->out); emit_c_literal(e->out,n->text,1); fputs(", sizeof(",e->out); emit_c_literal(e->out,n->text,1); fputs(")-1)",e->out); }
else if (n->text && n->text[0]=='"') {
fputs(n->sem_type && n->sem_type->maker ?
n->sem_type->maker : "fe_missing_str",e->out);
fputs("((const unsigned char*)",e->out);
emit_c_literal(e->out,n->text,1); fputs(", sizeof(",e->out);
emit_c_literal(e->out,n->text,1); fputs(")-1)",e->out);
}
else if (n->text && n->text[0]=='\'') emit_c_literal(e->out,n->text,0);
else fputs(n->text ? n->text : "0", e->out);
break;
@@ -775,6 +793,7 @@ static void emit_expr(FeEmitter *e, FeNode *n)
break;
case FE_N_CALL: {
FeVariantType *v;
FeNode *call_param=0;
int special=0;
if(n->text && (strcmp(n->text,"@print")==0 || strcmp(n->text,"@fprint")==0 || strcmp(n->text,"@sprint")==0)) { emit_m4_builtin(e,n); special=1; }
else if(n->a && n->a->kind==FE_N_MEMBER && n->a->a &&
@@ -814,14 +833,25 @@ static void emit_expr(FeEmitter *e, FeNode *n)
} else if (n->a) emit_expr(e, n->a);
else fputs(n->text ? n->text : "fe_builtin", e->out);
if(!special) {
if(n->sem_decl && n->sem_decl->kind==FE_N_FN && n->sem_decl->a)
call_param=n->sem_decl->a->children;
fputc('(', e->out);
for (x = n->children; x; x = x->next) {
FeType *want=call_param && call_param->a ?
fe_type_from_ast(&e->check->types,call_param->a) : 0;
if (x != n->children) fputs(", ", e->out);
if ((x->flags & 0x100U) && x->kind==FE_N_IDENT &&
if(want && want->kind==FE_TYPE_SLICE && !want->ref_mut &&
x->sem_type && x->sem_type->kind==FE_TYPE_SLICE &&
x->sem_type->ref_mut) {
fputs(want->maker,e->out); fputc('(',e->out);
emit_expr(e,x); fputs(".p, ",e->out);
emit_expr(e,x); fputs(".n)",e->out);
} else if ((x->flags & 0x100U) && x->kind==FE_N_IDENT &&
x->sem_type && x->sem_type->kind==FE_TYPE_OWNED) {
fputs("(fe_live_",e->out); fputs(cname(x,"owned"),e->out);
fputs("=0, ",e->out); emit_expr(e,x); fputc(')',e->out);
} else emit_expr(e, x);
if(call_param) call_param=call_param->next;
}
fputc(')', e->out);
}
+1
View File
@@ -49,6 +49,7 @@ static FeNode *type(FeParser *p)
if (is(p,FE_TOK_LBRACKET)) {
next(p); n=toknode(p,FE_N_TYPE,t);
if(!eat(p,FE_TOK_RBRACKET)) { n->a=expr(p,0); want(p,FE_TOK_RBRACKET,"expected ']' in array type"); }
else if(eat(p,FE_TOK_MUT)) n->text=fe_arena_strdup(&p->ast->arena,"[]mut",5);
n->b=type(p); return n;
}
if (is(p,FE_TOK_FN)) {
+28 -4
View File
@@ -64,7 +64,8 @@ FeType *fe_type_intern(FeTypeCtx *ctx, const char *name)
if (strcmp(name, "void") == 0) kind = FE_TYPE_VOID;
else if (strcmp(name, "bool") == 0) kind = FE_TYPE_BOOL;
else if (strcmp(name, "char") == 0) kind = FE_TYPE_CHAR;
else if (strcmp(name, "str") == 0) kind = FE_TYPE_STR;
else if (strcmp(name, "str") == 0)
return fe_type_slice(ctx, fe_type_intern(ctx, "u8"));
else if (strcmp(name, "io.Writer") == 0) {
kind = FE_TYPE_STRUCT;
}
@@ -156,6 +157,26 @@ FeType *fe_type_slice(FeTypeCtx *ctx, FeType *elem)
return t;
}
FeType *fe_type_mut_slice(FeTypeCtx *ctx, FeType *elem)
{
char key[96];
FeType *t;
sprintf(key, "[]mut %s", elem ? elem->name : "?");
t = fe_type_intern(ctx, key);
if (t->kind == FE_TYPE_UNKNOWN) {
t->kind = FE_TYPE_SLICE;
t->elem = elem;
t->ref_mut = 1;
t->cname = generated_name(ctx, "fe_mut_slice_", "type");
t->maker = generated_name(ctx, "fe_make_mut_slice_", "type");
t->indexer = generated_name(ctx, "fe_idx_mut_slice_", "type");
t->slicer = generated_name(ctx, "fe_slice_mut_slice_", "type");
t->full_slicer = generated_name(ctx, "fe_full_mut_slice_", "type");
t->tail_slicer = generated_name(ctx, "fe_tail_mut_slice_", "type");
}
return t;
}
FeType *fe_type_ref(FeTypeCtx *ctx, FeType *elem, int mutable)
{
char key[128];
@@ -478,7 +499,7 @@ FeType *fe_type_from_ast(FeTypeCtx *ctx, const FeNode *node)
if (node->text && strcmp(node->text, "as") == 0)
return fe_type_from_ast(ctx, node->b);
if (node->text && strcmp(node->text, "str") == 0)
return fe_type_intern(ctx, "str");
return fe_type_slice(ctx, fe_type_intern(ctx, "u8"));
if (node->a && node->a->kind==FE_N_IDENT && node->text &&
strcmp(node->text,"io")==0 && node->a->text) {
sprintf(qualified,"%s.%s",node->text,node->a->text);
@@ -490,13 +511,16 @@ FeType *fe_type_from_ast(FeTypeCtx *ctx, const FeNode *node)
strcmp(node->text,"&mut") == 0);
if (node->text && strcmp(node->text,"^")==0)
return fe_type_owned(ctx,fe_type_from_ast(ctx,node->a));
if (node->text && strcmp(node->text, "[") == 0) {
if (node->text && (strcmp(node->text, "[") == 0 ||
strcmp(node->text, "[]mut") == 0)) {
if (node->a) {
if (node->a->kind == FE_N_LITERAL && node->a->text)
length = strtoul(node->a->text, 0, 0);
return fe_type_array(ctx, length, fe_type_from_ast(ctx, node->b));
}
return fe_type_slice(ctx, fe_type_from_ast(ctx, node->b));
return strcmp(node->text,"[]mut")==0 ?
fe_type_mut_slice(ctx, fe_type_from_ast(ctx,node->b)) :
fe_type_slice(ctx, fe_type_from_ast(ctx, node->b));
}
if (node->text && strcmp(node->text, "!") == 0)
/* Prefix !T stores T in a; the E!T spelling stores its success
+1
View File
@@ -73,6 +73,7 @@ FeType *fe_type_intern(FeTypeCtx *ctx, const char *name);
FeType *fe_type_from_ast(FeTypeCtx *ctx, const FeNode *node);
FeType *fe_type_array(FeTypeCtx *ctx, unsigned long length, FeType *elem);
FeType *fe_type_slice(FeTypeCtx *ctx, FeType *elem);
FeType *fe_type_mut_slice(FeTypeCtx *ctx, FeType *elem);
FeType *fe_type_ref(FeTypeCtx *ctx, FeType *elem, int mutable);
FeType *fe_type_owned(FeTypeCtx *ctx, FeType *elem);
FeType *fe_type_error_union(FeTypeCtx *ctx, FeType *value);
+36 -20
View File
@@ -15,9 +15,9 @@ fec.exe --dump-ast TESTS\PASS\BASIC.FE > nul
if errorlevel 1 goto test_fail
fec.exe --dump-ast TESTS\PASS\LITERALS.FE > nul
if errorlevel 1 goto test_fail
fec.exe --dump-ast TESTS\PASS\KEYWORDS-AND-BUILTINS.FE > nul
fec.exe --dump-ast TESTS\PASS\KEYBUILT.FE > nul
if errorlevel 1 goto test_fail
fec.exe --dump-ast TESTS\PASS\V012-FORMS.FE > nul
fec.exe --dump-ast TESTS\PASS\V012FORM.FE > nul
if errorlevel 1 goto test_fail
fec.exe --dump-ast STD\CORE.FE > nul
@@ -37,11 +37,11 @@ if errorlevel 1 goto test_fail
fec.exe --dump-ast STD\SYS.FE > nul
if errorlevel 1 goto test_fail
fec.exe --dump-ast TESTS\FAIL\MISSING-SEMI.FE > nul
fec.exe --dump-ast TESTS\FAIL\MISSSEMI.FE > nul
if not errorlevel 1 goto test_fail
fec.exe --dump-ast TESTS\FAIL\UNCLOSED-COMMENT.FE > nul
fec.exe --dump-ast TESTS\FAIL\UNCLCOMM.FE > nul
if not errorlevel 1 goto test_fail
fec.exe --dump-ast TESTS\FAIL\LOGICAL-SYMBOLS.FE > nul
fec.exe --dump-ast TESTS\FAIL\LOGICAL.FE > nul
if not errorlevel 1 goto test_fail
if exist TESTS\M2\HELLO.C del TESTS\M2\HELLO.C
@@ -67,28 +67,28 @@ TESTS\M2\SCOPES.EXE
if errorlevel 1 goto test_fail
rem M2 bits16 regression path remains on compiler A (wcl).
fec.exe --target=bits16 --emit-c TESTS\M2\CAST-WHILE.FE -o TESTS\M2\CAST16.C > nul
fec.exe --target=bits16 --emit-c TESTS\M2\CASTWHIL.FE -o TESTS\M2\CAST16.C > nul
if errorlevel 1 goto test_fail
wcl -q -za -bt=dos -fe=TESTS\M2\CAST16.EXE TESTS\M2\CAST16.C
if errorlevel 1 goto test_fail
TESTS\M2\CAST16.EXE
if errorlevel 1 goto test_fail
fec.exe --target=bits32 --emit-c TESTS\M2\BAD-CONDITION.FE -o TESTS\M2\BAD-CO.C > nul
fec.exe --target=bits32 --emit-c TESTS\M2\BAD-COND.FE -o TESTS\M2\BAD-CO.C > nul
if not errorlevel 1 goto test_fail
fec.exe --target=bits32 --emit-c TESTS\M2\BAD-CAST.FE -o TESTS\M2\BAD-CA.C > nul
if not errorlevel 1 goto test_fail
fec.exe --target=bits32 --emit-c TESTS\M2\BAD-ASSIGN.FE -o TESTS\M2\BAD-AS.C > nul
fec.exe --target=bits32 --emit-c TESTS\M2\BAD-ASGN.FE -o TESTS\M2\BAD-AS.C > nul
if not errorlevel 1 goto test_fail
fec.exe --target=bits32 --emit-c TESTS\M2\BAD-UNKNOWN.FE -o TESTS\M2\BAD-UN.C > nul
fec.exe --target=bits32 --emit-c TESTS\M2\BAD-UNK.FE -o TESTS\M2\BAD-UN.C > nul
if not errorlevel 1 goto test_fail
fec.exe --target=bits32 --emit-c TESTS\M2\BAD-ARITY.FE -o TESTS\M2\BAD-AR.C > nul
fec.exe --target=bits32 --emit-c TESTS\M2\BAD-ARI.FE -o TESTS\M2\BAD-AR.C > nul
if not errorlevel 1 goto test_fail
fec.exe --target=bits32 --emit-c TESTS\M2\BAD-TYPES.FE -o TESTS\M2\BAD-TY.C > nul
fec.exe --target=bits32 --emit-c TESTS\M2\BAD-TYPE.FE -o TESTS\M2\BAD-TY.C > nul
if not errorlevel 1 goto test_fail
fec.exe --target=bits32 --emit-c TESTS\M2\BAD-RETURN.FE -o TESTS\M2\BAD-RE.C > nul
fec.exe --target=bits32 --emit-c TESTS\M2\BAD-RET.FE -o TESTS\M2\BAD-RE.C > nul
if not errorlevel 1 goto test_fail
fec.exe --target=bits32 --emit-c TESTS\M2\BAD-UNINIT.FE -o TESTS\M2\BAD-UI.C > nul
fec.exe --target=bits32 --emit-c TESTS\M2\BAD-UNIT.FE -o TESTS\M2\BAD-UI.C > nul
if not errorlevel 1 goto test_fail
fec.exe --target=bits32 --emit-c TESTS\M2\BAD-VOID.FE -o TESTS\M2\BAD-VO.C > nul
if not errorlevel 1 goto test_fail
@@ -132,6 +132,16 @@ wcl386 -q -za -bt=dos -fe=TESTS\M3\ARRAY.EXE TESTS\M3\ARRAY.C
if errorlevel 1 goto test_fail
TESTS\M3\ARRAY.EXE
if errorlevel 1 goto test_fail
fec.exe --target=bits32 --emit-c TESTS\M3\MUTABLE.FE -o TESTS\M3\MUTABLE.C > nul
if errorlevel 1 goto test_fail
wcl386 -q -za -bt=dos -fe=TESTS\M3\MUTABLE.EXE TESTS\M3\MUTABLE.C
if errorlevel 1 goto test_fail
TESTS\M3\MUTABLE.EXE
if errorlevel 1 goto test_fail
fec.exe --target=bits32 --emit-c TESTS\M3\BAD-MLET.FE -o TESTS\M3\BAD-MLET.C > nul
if not errorlevel 1 goto test_fail
fec.exe --target=bits32 --emit-c TESTS\M3\BAD-SHWR.FE -o TESTS\M3\BAD-SHWR.C > nul
if not errorlevel 1 goto test_fail
fec.exe --target=bits32 --emit-c TESTS\M3\STR.FE -o TESTS\M3\STR.C > nul
if errorlevel 1 goto test_fail
wcl386 -q -za -bt=dos -fe=TESTS\M3\STR.EXE TESTS\M3\STR.C
@@ -168,6 +178,12 @@ wcl386 -q -za -bt=dos -fe=TESTS\M3\BOUNDS.EXE TESTS\M3\BOUNDS.C
if errorlevel 1 goto test_fail
TESTS\M3\BOUNDS.EXE
if not errorlevel 1 goto test_fail
fec.exe --target=bits32 --emit-c TESTS\M3\SLCBOUND.FE -o TESTS\M3\SLCBOUND.C > nul
if errorlevel 1 goto test_fail
wcl386 -q -za -bt=dos -fe=TESTS\M3\SLCBOUND.EXE TESTS\M3\SLCBOUND.C
if errorlevel 1 goto test_fail
TESTS\M3\SLCBOUND.EXE
if not errorlevel 1 goto test_fail
fec.exe --target=bits32 --no-checks --emit-c TESTS\M3\BOUNDS.FE -o TESTS\M3\BOUNDS-N.C > nul
if errorlevel 1 goto test_fail
wcl386 -q -za -bt=dos -fe=TESTS\M3\BOUNDS-N.EXE TESTS\M3\BOUNDS-N.C
@@ -197,7 +213,7 @@ wcl386 -q -za -wx -wcd=202 -bt=dos -fe=TESTS\M4\FORMAT.EXE TESTS\M4\FORMAT.C
if errorlevel 1 goto test_fail
TESTS\M4\FORMAT.EXE > nul
if errorlevel 1 goto test_fail
fec.exe --target=bits32 --emit-c TESTS\M4\TRY-FPRINT.FE -o TESTS\M4\TRY-FPR.C > nul
fec.exe --target=bits32 --emit-c TESTS\M4\TRY-FPR.FE -o TESTS\M4\TRY-FPR.C > nul
if errorlevel 1 goto test_fail
wcl386 -q -za -wx -wcd=202 -bt=dos -fe=TESTS\M4\TRY-FPR.EXE TESTS\M4\TRY-FPR.C
if errorlevel 1 goto test_fail
@@ -209,17 +225,17 @@ wcl386 -q -za -wx -wcd=202 -bt=dos -fe=TESTS\M4\PROP.EXE TESTS\M4\PROPTEST.C
if errorlevel 1 goto test_fail
TESTS\M4\PROP.EXE > nul
if errorlevel 1 goto test_fail
fec.exe --target=bits32 --emit-c TESTS\M4\BAD-ARITY.FE -o TESTS\M4\BAD-ARI.C > nul
fec.exe --target=bits32 --emit-c TESTS\M4\BAD-ARI.FE -o TESTS\M4\BAD-ARI.C > nul
if not errorlevel 1 goto test_fail
fec.exe --target=bits32 --emit-c TESTS\M4\BAD-VERB.FE -o TESTS\M4\BAD-VERB.C > nul
if not errorlevel 1 goto test_fail
fec.exe --target=bits32 --emit-c TESTS\M4\BAD-RUNTIME.FE -o TESTS\M4\BAD-RUN.C > nul
fec.exe --target=bits32 --emit-c TESTS\M4\BAD-RUN.FE -o TESTS\M4\BAD-RUN.C > nul
if not errorlevel 1 goto test_fail
fec.exe --target=bits32 --emit-c TESTS\M4\BAD-TYPE.FE -o TESTS\M4\BAD-TYP.C > nul
if not errorlevel 1 goto test_fail
fec.exe --target=bits32 --emit-c TESTS\M4\BAD-TRY.FE -o TESTS\M4\BAD-TRY.C > nul
if not errorlevel 1 goto test_fail
fec.exe --target=bits32 --emit-c TESTS\M4\BAD-WRITER.FE -o TESTS\M4\BAD-WRI.C > nul
fec.exe --target=bits32 --emit-c TESTS\M4\BAD-WRIT.FE -o TESTS\M4\BAD-WRI.C > nul
if not errorlevel 1 goto test_fail
fec.exe --target=bits32 --emit-c TESTS\M4\BAD-MANY.FE -o TESTS\M4\BAD-MANY.C > nul
if not errorlevel 1 goto test_fail
@@ -233,13 +249,13 @@ fec.exe --target=bits32 --emit-c TESTS\M5\OWNED.FE -o TESTS\M5\OWNED.C > nul
if errorlevel 1 goto test_fail
fec.exe --target=bits32 --emit-c TESTS\M5\BAD-MOVE.FE -o TESTS\M5\BAD-MOVE.C > nul
if not errorlevel 1 goto test_fail
fec.exe --target=bits32 --emit-c TESTS\M5\BAD-DESTROY.FE -o TESTS\M5\BAD-DES.C > nul
fec.exe --target=bits32 --emit-c TESTS\M5\BAD-DEST.FE -o TESTS\M5\BAD-DES.C > nul
if not errorlevel 1 goto test_fail
fec.exe --target=bits32 --emit-c TESTS\M5\BAD-DROP.FE -o TESTS\M5\BAD-DROP.C > nul
if not errorlevel 1 goto test_fail
fec.exe --target=bits32 --emit-c TESTS\M5\BAD-DOUBLE.FE -o TESTS\M5\BAD-DBL.C > nul
fec.exe --target=bits32 --emit-c TESTS\M5\BAD-DBL.FE -o TESTS\M5\BAD-DBL.C > nul
if not errorlevel 1 goto test_fail
fec.exe --target=bits32 --emit-c TESTS\M5\BAD-CONDITIONAL.FE -o TESTS\M5\BAD-COND.C > nul
fec.exe --target=bits32 --emit-c TESTS\M5\BAD-COND.FE -o TESTS\M5\BAD-COND.C > nul
if not errorlevel 1 goto test_fail
if exist TESTS\M5\RUNTIME-G.C del TESTS\M5\RUNTIME-G.C
if exist TESTS\M5\RUNTIME.O del TESTS\M5\RUNTIME.O
+6
View File
@@ -0,0 +1,6 @@
unit m3_bad_mut_let;
fn bad() -> void {
var raw: [2]u8 = [1, 2];
let s: []mut u8 = raw[..];
}
+5
View File
@@ -0,0 +1,5 @@
unit m3_bad_shared_write;
fn bad(s: []u8) -> void {
s[0] = 1;
}
+11
View File
@@ -0,0 +1,11 @@
unit m3_mutable;
fn takes_shared(s: []u8) -> u8 { return s[0]; }
fn main() -> i32 {
var raw: [3]u8 = [1, 2, 3];
var s: []mut u8 = raw[..];
s[1] = 9;
if takes_shared(s) == 1 and raw[1] == 9 { return 0; }
return 1;
}
+7
View File
@@ -0,0 +1,7 @@
unit m3_slice_bounds;
fn main() -> i32 {
let a: [2]i32 = [1, 2];
let s: []i32 = a[0..3];
return s.n as i32;
}