feat: align M3 slices and strings with v0.1.7
This commit is contained in:
+1
-1
@@ -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));
|
FeNode *n=(FeNode *)fe_arena_alloc(&a->arena,sizeof(FeNode));
|
||||||
if (!n) return 0;
|
if (!n) return 0;
|
||||||
n->kind=k; n->loc=loc; n->text=text?fe_arena_strdup(&a->arena,text,len):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)
|
void fe_node_add(FeNode *parent, FeNode *child)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ struct FeNode {
|
|||||||
char *aux_text;
|
char *aux_text;
|
||||||
char *aux_cname;
|
char *aux_cname;
|
||||||
FeType *sem_type;
|
FeType *sem_type;
|
||||||
|
FeNode *sem_decl;
|
||||||
unsigned flags;
|
unsigned flags;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
+37
-16
@@ -54,7 +54,7 @@ static int is_copy_type(FeType *t)
|
|||||||
unsigned i;
|
unsigned i;
|
||||||
if (!t) return 1;
|
if (!t) return 1;
|
||||||
if (t->kind==FE_TYPE_OWNED) return 0;
|
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_ARRAY) return is_copy_type(t->elem);
|
||||||
if (t->kind==FE_TYPE_STRUCT) {
|
if (t->kind==FE_TYPE_STRUCT) {
|
||||||
if (t->has_drop) return 0;
|
if (t->has_drop) return 0;
|
||||||
@@ -311,6 +311,8 @@ static FeNode *find_const_node(FeCheck *c, const char *name)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int format_is_slice_u8(FeType *t);
|
||||||
|
|
||||||
static const char *builtin_format(FeCheckerState *s, FeNode *fmt)
|
static const char *builtin_format(FeCheckerState *s, FeNode *fmt)
|
||||||
{
|
{
|
||||||
FeNode *decl;
|
FeNode *decl;
|
||||||
@@ -323,7 +325,7 @@ static const char *builtin_format(FeCheckerState *s, FeNode *fmt)
|
|||||||
sym->decl : find_const_node(s->c,fmt->text);
|
sym->decl : find_const_node(s->c,fmt->text);
|
||||||
if (decl && decl->b && decl->b->kind==FE_N_LITERAL &&
|
if (decl && decl->b && decl->b->kind==FE_N_LITERAL &&
|
||||||
decl->b->text && decl->b->text[0]=='"') {
|
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;
|
return decl->b->text;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -347,10 +349,10 @@ static int format_arg_ok(FeType *t, int verb)
|
|||||||
if (!t) return 0;
|
if (!t) return 0;
|
||||||
if (verb=='x') return fe_type_is_integer(t);
|
if (verb=='x') return fe_type_is_integer(t);
|
||||||
if (verb=='c') return t->kind==FE_TYPE_CHAR;
|
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 (verb=='b') return t->kind==FE_TYPE_BOOL;
|
||||||
if (t->kind==FE_TYPE_INT || 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) ||
|
return format_is_slice_u8(t) ||
|
||||||
(t->kind==FE_TYPE_ENUM && t->is_error);
|
(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 (strcmp(n->text,"@sprint")==0) {
|
||||||
if (!fmt_node) { err(s->c,n->loc,"@sprint requires a buffer"); return; }
|
if (!fmt_node) { err(s->c,n->loc,"@sprint requires a buffer"); return; }
|
||||||
t=check_expr(s,fmt_node);
|
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_node=fmt_node->next;
|
||||||
}
|
}
|
||||||
fmt=builtin_format(s,fmt_node);
|
fmt=builtin_format(s,fmt_node);
|
||||||
@@ -517,7 +520,18 @@ static FeType *check_index(FeCheckerState *s, FeNode *n)
|
|||||||
if(n->c || !n->b) {
|
if(n->c || !n->b) {
|
||||||
if (base->kind==FE_TYPE_ARRAY && !array_slice_lvalue(n->a))
|
if (base->kind==FE_TYPE_ARRAY && !array_slice_lvalue(n->a))
|
||||||
err(s->c,n->loc,"array slicing requires a stable lvalue");
|
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;
|
n->sem_type=base->elem; return n->sem_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -715,6 +729,7 @@ static FeType *check_expr(FeCheckerState *s, FeNode *n)
|
|||||||
return unknown(c);
|
return unknown(c);
|
||||||
}
|
}
|
||||||
n->a->cname = sym->cname;
|
n->a->cname = sym->cname;
|
||||||
|
n->sem_decl = sym->fn;
|
||||||
if (!sym->fn) {
|
if (!sym->fn) {
|
||||||
err(c, n->loc, "name is not a function");
|
err(c, n->loc, "name is not a function");
|
||||||
return unknown(c);
|
return unknown(c);
|
||||||
@@ -725,7 +740,10 @@ static FeType *check_expr(FeCheckerState *s, FeNode *n)
|
|||||||
a = check_expr(s, arg);
|
a = check_expr(s, arg);
|
||||||
mark_moved(s,arg,a);
|
mark_moved(s,arg,a);
|
||||||
b = node_type(c, param->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");
|
err(c, arg->loc, "argument type mismatch");
|
||||||
param = param->next;
|
param = param->next;
|
||||||
arg = arg->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;
|
n->sem_type=field->type; return field->type;
|
||||||
}
|
}
|
||||||
if (n && n->kind == FE_N_INDEX) {
|
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);
|
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;
|
return base;
|
||||||
}
|
}
|
||||||
if (n) err(s->c, n->loc, "assignment requires a variable");
|
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 &&
|
else if (n->a && n->a->kind==FE_N_INDEX && n->a->a &&
|
||||||
n->a->a->kind==FE_N_IDENT)
|
n->a->a->kind==FE_N_IDENT)
|
||||||
iter_sym=find_symbol(s->scope,n->a->a->text ? n->a->a->text : "");
|
iter_sym=find_symbol(s->scope,n->a->a->text ? n->a->a->text : "");
|
||||||
iter_mut=iter_sym && iter_sym->mutable;
|
iter_mut=start->kind==FE_TYPE_SLICE ? start->ref_mut :
|
||||||
if (start->kind==FE_TYPE_STR) iter_mut=0;
|
(iter_sym && iter_sym->mutable);
|
||||||
ref_type=fe_type_ref(&s->c->types,elem,iter_mut);
|
ref_type=fe_type_ref(&s->c->types,elem,iter_mut);
|
||||||
if (iter_mut) n->flags |= 4U;
|
if (iter_mut) n->flags |= 4U;
|
||||||
s->scope=scope_new(s,old);
|
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");
|
err(c, n->loc, "initializer type mismatch");
|
||||||
if (b->kind == FE_TYPE_VOID)
|
if (b->kind == FE_TYPE_VOID)
|
||||||
err(c, n->loc, "void expression cannot initialize a variable");
|
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);
|
mark_moved(s,n->b,b);
|
||||||
add_symbol(s, s->scope, n->text, a, 0, 0, 1,
|
add_symbol(s, s->scope, n->text, a, 0, 0, 1,
|
||||||
local_cname(c, n->text ? n->text : "local"), n);
|
local_cname(c, n->text ? n->text : "local"), n);
|
||||||
|
|||||||
+49
-19
@@ -75,8 +75,10 @@ static void emit_one_type(FeEmitter *e, FeType *t)
|
|||||||
} else if(t->kind==FE_TYPE_ARRAY) {
|
} 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);
|
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) {
|
} 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);
|
fputs("typedef struct { ",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);
|
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) {
|
} else if(t->kind==FE_TYPE_ERROR_UNION) {
|
||||||
fputs(t->cname,e->out); fputs(" { unsigned short e; ",e->out);
|
fputs(t->cname,e->out); fputs(" { unsigned short e; ",e->out);
|
||||||
fputs(fe_type_c_name(t->error_value,e->pointer_bits),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)
|
static void emit_type_defs(FeEmitter *e)
|
||||||
{
|
{
|
||||||
FeType *t;
|
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
|
/* Every fixed array has a slice conversion helper, even if this unit
|
||||||
only indexes the array. Intern those result types before emission so
|
only indexes the array. Intern those result types before emission so
|
||||||
their typedefs are present before helper definitions. */
|
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);
|
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)
|
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 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_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_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("#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_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);
|
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') {
|
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;
|
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 (verb=='s' || (verb==' ' && t && t->kind==FE_TYPE_SLICE)) {
|
||||||
if (t && t->kind==FE_TYPE_STR) fputs("fe_m4_write_str(",e->out);
|
fputs("fe_m4_write_slice(",e->out);
|
||||||
else 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;
|
emit_m4_writer_value(e,writer,buffer); fputs(", ",e->out); emit_expr(e,arg); fputc(')',e->out); return;
|
||||||
}
|
}
|
||||||
if (error_value) {
|
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)
|
static void emit_slice_call(FeEmitter *e, FeNode *n)
|
||||||
{
|
{
|
||||||
FeType *bt=n->a ? n->a->sem_type : 0;
|
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) {
|
if (!n->b && !n->c && bt && bt->full_slicer) {
|
||||||
fputs(bt->full_slicer,e->out);
|
fputs(bt->full_slicer,e->out);
|
||||||
if (bt->kind==FE_TYPE_ARRAY) { fputs("(&",e->out); emit_lvalue(e,n->a); }
|
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:
|
case FE_N_LITERAL:
|
||||||
if (n->text && strcmp(n->text, "true") == 0) fputs("1", e->out);
|
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 && 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 if (n->text && n->text[0]=='\'') emit_c_literal(e->out,n->text,0);
|
||||||
else fputs(n->text ? n->text : "0", e->out);
|
else fputs(n->text ? n->text : "0", e->out);
|
||||||
break;
|
break;
|
||||||
@@ -775,6 +793,7 @@ static void emit_expr(FeEmitter *e, FeNode *n)
|
|||||||
break;
|
break;
|
||||||
case FE_N_CALL: {
|
case FE_N_CALL: {
|
||||||
FeVariantType *v;
|
FeVariantType *v;
|
||||||
|
FeNode *call_param=0;
|
||||||
int special=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; }
|
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 &&
|
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 if (n->a) emit_expr(e, n->a);
|
||||||
else fputs(n->text ? n->text : "fe_builtin", e->out);
|
else fputs(n->text ? n->text : "fe_builtin", e->out);
|
||||||
if(!special) {
|
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);
|
fputc('(', e->out);
|
||||||
for (x = n->children; x; x = x->next) {
|
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 != 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) {
|
x->sem_type && x->sem_type->kind==FE_TYPE_OWNED) {
|
||||||
fputs("(fe_live_",e->out); fputs(cname(x,"owned"),e->out);
|
fputs("(fe_live_",e->out); fputs(cname(x,"owned"),e->out);
|
||||||
fputs("=0, ",e->out); emit_expr(e,x); fputc(')',e->out);
|
fputs("=0, ",e->out); emit_expr(e,x); fputc(')',e->out);
|
||||||
} else emit_expr(e, x);
|
} else emit_expr(e, x);
|
||||||
|
if(call_param) call_param=call_param->next;
|
||||||
}
|
}
|
||||||
fputc(')', e->out);
|
fputc(')', e->out);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -49,6 +49,7 @@ static FeNode *type(FeParser *p)
|
|||||||
if (is(p,FE_TOK_LBRACKET)) {
|
if (is(p,FE_TOK_LBRACKET)) {
|
||||||
next(p); n=toknode(p,FE_N_TYPE,t);
|
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"); }
|
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;
|
n->b=type(p); return n;
|
||||||
}
|
}
|
||||||
if (is(p,FE_TOK_FN)) {
|
if (is(p,FE_TOK_FN)) {
|
||||||
|
|||||||
+28
-4
@@ -64,7 +64,8 @@ FeType *fe_type_intern(FeTypeCtx *ctx, const char *name)
|
|||||||
if (strcmp(name, "void") == 0) kind = FE_TYPE_VOID;
|
if (strcmp(name, "void") == 0) kind = FE_TYPE_VOID;
|
||||||
else if (strcmp(name, "bool") == 0) kind = FE_TYPE_BOOL;
|
else if (strcmp(name, "bool") == 0) kind = FE_TYPE_BOOL;
|
||||||
else if (strcmp(name, "char") == 0) kind = FE_TYPE_CHAR;
|
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) {
|
else if (strcmp(name, "io.Writer") == 0) {
|
||||||
kind = FE_TYPE_STRUCT;
|
kind = FE_TYPE_STRUCT;
|
||||||
}
|
}
|
||||||
@@ -156,6 +157,26 @@ FeType *fe_type_slice(FeTypeCtx *ctx, FeType *elem)
|
|||||||
return t;
|
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)
|
FeType *fe_type_ref(FeTypeCtx *ctx, FeType *elem, int mutable)
|
||||||
{
|
{
|
||||||
char key[128];
|
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)
|
if (node->text && strcmp(node->text, "as") == 0)
|
||||||
return fe_type_from_ast(ctx, node->b);
|
return fe_type_from_ast(ctx, node->b);
|
||||||
if (node->text && strcmp(node->text, "str") == 0)
|
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 &&
|
if (node->a && node->a->kind==FE_N_IDENT && node->text &&
|
||||||
strcmp(node->text,"io")==0 && node->a->text) {
|
strcmp(node->text,"io")==0 && node->a->text) {
|
||||||
sprintf(qualified,"%s.%s",node->text,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);
|
strcmp(node->text,"&mut") == 0);
|
||||||
if (node->text && strcmp(node->text,"^")==0)
|
if (node->text && strcmp(node->text,"^")==0)
|
||||||
return fe_type_owned(ctx,fe_type_from_ast(ctx,node->a));
|
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) {
|
||||||
if (node->a->kind == FE_N_LITERAL && node->a->text)
|
if (node->a->kind == FE_N_LITERAL && node->a->text)
|
||||||
length = strtoul(node->a->text, 0, 0);
|
length = strtoul(node->a->text, 0, 0);
|
||||||
return fe_type_array(ctx, length, fe_type_from_ast(ctx, node->b));
|
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)
|
if (node->text && strcmp(node->text, "!") == 0)
|
||||||
/* Prefix !T stores T in a; the E!T spelling stores its success
|
/* Prefix !T stores T in a; the E!T spelling stores its success
|
||||||
|
|||||||
@@ -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_from_ast(FeTypeCtx *ctx, const FeNode *node);
|
||||||
FeType *fe_type_array(FeTypeCtx *ctx, unsigned long length, FeType *elem);
|
FeType *fe_type_array(FeTypeCtx *ctx, unsigned long length, FeType *elem);
|
||||||
FeType *fe_type_slice(FeTypeCtx *ctx, 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_ref(FeTypeCtx *ctx, FeType *elem, int mutable);
|
||||||
FeType *fe_type_owned(FeTypeCtx *ctx, FeType *elem);
|
FeType *fe_type_owned(FeTypeCtx *ctx, FeType *elem);
|
||||||
FeType *fe_type_error_union(FeTypeCtx *ctx, FeType *value);
|
FeType *fe_type_error_union(FeTypeCtx *ctx, FeType *value);
|
||||||
|
|||||||
+36
-20
@@ -15,9 +15,9 @@ fec.exe --dump-ast TESTS\PASS\BASIC.FE > nul
|
|||||||
if errorlevel 1 goto test_fail
|
if errorlevel 1 goto test_fail
|
||||||
fec.exe --dump-ast TESTS\PASS\LITERALS.FE > nul
|
fec.exe --dump-ast TESTS\PASS\LITERALS.FE > nul
|
||||||
if errorlevel 1 goto test_fail
|
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
|
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
|
if errorlevel 1 goto test_fail
|
||||||
|
|
||||||
fec.exe --dump-ast STD\CORE.FE > nul
|
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
|
fec.exe --dump-ast STD\SYS.FE > nul
|
||||||
if errorlevel 1 goto test_fail
|
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
|
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
|
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 not errorlevel 1 goto test_fail
|
||||||
|
|
||||||
if exist TESTS\M2\HELLO.C del TESTS\M2\HELLO.C
|
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
|
if errorlevel 1 goto test_fail
|
||||||
|
|
||||||
rem M2 bits16 regression path remains on compiler A (wcl).
|
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
|
if errorlevel 1 goto test_fail
|
||||||
wcl -q -za -bt=dos -fe=TESTS\M2\CAST16.EXE TESTS\M2\CAST16.C
|
wcl -q -za -bt=dos -fe=TESTS\M2\CAST16.EXE TESTS\M2\CAST16.C
|
||||||
if errorlevel 1 goto test_fail
|
if errorlevel 1 goto test_fail
|
||||||
TESTS\M2\CAST16.EXE
|
TESTS\M2\CAST16.EXE
|
||||||
if errorlevel 1 goto test_fail
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
if errorlevel 1 goto test_fail
|
||||||
TESTS\M3\ARRAY.EXE
|
TESTS\M3\ARRAY.EXE
|
||||||
if errorlevel 1 goto test_fail
|
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
|
fec.exe --target=bits32 --emit-c TESTS\M3\STR.FE -o TESTS\M3\STR.C > nul
|
||||||
if errorlevel 1 goto test_fail
|
if errorlevel 1 goto test_fail
|
||||||
wcl386 -q -za -bt=dos -fe=TESTS\M3\STR.EXE TESTS\M3\STR.C
|
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
|
if errorlevel 1 goto test_fail
|
||||||
TESTS\M3\BOUNDS.EXE
|
TESTS\M3\BOUNDS.EXE
|
||||||
if not errorlevel 1 goto test_fail
|
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
|
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
|
if errorlevel 1 goto test_fail
|
||||||
wcl386 -q -za -bt=dos -fe=TESTS\M3\BOUNDS-N.EXE TESTS\M3\BOUNDS-N.C
|
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
|
if errorlevel 1 goto test_fail
|
||||||
TESTS\M4\FORMAT.EXE > nul
|
TESTS\M4\FORMAT.EXE > nul
|
||||||
if errorlevel 1 goto test_fail
|
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
|
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
|
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
|
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
|
if errorlevel 1 goto test_fail
|
||||||
TESTS\M4\PROP.EXE > nul
|
TESTS\M4\PROP.EXE > nul
|
||||||
if errorlevel 1 goto test_fail
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
if errorlevel 1 goto test_fail
|
||||||
fec.exe --target=bits32 --emit-c TESTS\M5\BAD-MOVE.FE -o TESTS\M5\BAD-MOVE.C > nul
|
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
|
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
|
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
|
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
|
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
|
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 not errorlevel 1 goto test_fail
|
||||||
if exist TESTS\M5\RUNTIME-G.C del TESTS\M5\RUNTIME-G.C
|
if exist TESTS\M5\RUNTIME-G.C del TESTS\M5\RUNTIME-G.C
|
||||||
if exist TESTS\M5\RUNTIME.O del TESTS\M5\RUNTIME.O
|
if exist TESTS\M5\RUNTIME.O del TESTS\M5\RUNTIME.O
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
unit m3_bad_mut_let;
|
||||||
|
|
||||||
|
fn bad() -> void {
|
||||||
|
var raw: [2]u8 = [1, 2];
|
||||||
|
let s: []mut u8 = raw[..];
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
unit m3_bad_shared_write;
|
||||||
|
|
||||||
|
fn bad(s: []u8) -> void {
|
||||||
|
s[0] = 1;
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user