diff --git a/src/tools/ainedit/jaf_compile.c b/src/tools/ainedit/jaf_compile.c index 6c339bc..aa1eacf 100644 --- a/src/tools/ainedit/jaf_compile.c +++ b/src/tools/ainedit/jaf_compile.c @@ -182,6 +182,24 @@ static void compile_unary(struct ain *ain, struct buffer *out, struct jaf_expres } } +static void compile_lvalue(possibly_unused struct ain *ain, struct buffer *out, struct jaf_expression *expr) +{ + if (expr->type == JAF_EXP_IDENTIFIER) { + if (expr->ident.var_type == AIN_VAR_GLOBAL) { + write_instruction0(out, PUSHGLOBALPAGE); + } else if (expr->ident.var_type == AIN_VAR_LOCAL) { + write_instruction0(out, PUSHLOCALPAGE); + } else { + ERROR("Invalid variable type as lvalue"); + } + write_instruction1(out, PUSH, expr->ident.var_no); + } else if (expr->type == JAF_EXP_MEMBER) { + ERROR("struct member lvalues not supported"); + } else { + ERROR("Invalid lvalue"); + } +} + static void compile_binary(struct ain *ain, struct buffer *out, struct jaf_expression *expr) { switch (expr->op) { @@ -223,7 +241,10 @@ static void compile_binary(struct ain *ain, struct buffer *out, struct jaf_expre case JAF_XOR_ASSIGN: case JAF_OR_ASSIGN: case JAF_REF_ASSIGN: - ERROR("Assignment not supported"); + compile_lvalue(ain, out, expr->lhs); + compile_expression(ain, out, expr->rhs); + write_instruction0(out, jaf_op_to_opcode(expr->op, expr->value_type.type)); + break; default: ERROR("Invalid binary operator"); } @@ -340,6 +361,7 @@ static void compile_vardecl(struct ain *ain, struct buffer *out, struct jaf_decl write_instruction1(out, PUSH, 0); } write_instruction0(out, ASSIGN); + write_instruction0(out, POP); break; case JAF_FLOAT: write_instruction0(out, PUSHLOCALPAGE); @@ -349,6 +371,8 @@ static void compile_vardecl(struct ain *ain, struct buffer *out, struct jaf_decl } else { write_instruction1(out, F_PUSH, 0); } + write_instruction0(out, F_ASSIGN); + write_instruction0(out, POP); break; case JAF_STRING: ERROR("strings not supported"); diff --git a/src/tools/ainedit/jaf_static_analysis.c b/src/tools/ainedit/jaf_static_analysis.c index d8fa041..dadc116 100644 --- a/src/tools/ainedit/jaf_static_analysis.c +++ b/src/tools/ainedit/jaf_static_analysis.c @@ -321,12 +321,13 @@ static void jaf_resolve_types(struct ain *ain, struct jaf_block *block) } } -static void init_variable(struct ain *ain, struct ain_variable *var, struct string *name, struct jaf_type_specifier *type) +static void init_variable(struct ain *ain, struct ain_variable *var, struct jaf_declaration *decl, int var_no) { - var->name = encode_text_to_input_format(name->text); + var->name = encode_text_to_input_format(decl->name->text); if (ain->version >= 12) var->name2 = strdup(""); - jaf_to_ain_type(ain, &var->type, type); + jaf_to_ain_type(ain, &var->type, decl->type); + decl->var_no = var_no; } static struct ain_variable *block_get_vars(struct ain *ain, struct jaf_block *block, struct ain_variable *vars, int *nr_vars); @@ -338,7 +339,7 @@ static struct ain_variable *block_item_get_vars(struct ain *ain, struct jaf_bloc if (!item->decl.name) break; vars = xrealloc_array(vars, *nr_vars, *nr_vars + 1, sizeof(struct ain_variable)); - init_variable(ain, vars + *nr_vars, item->decl.name, item->decl.type); + init_variable(ain, vars + *nr_vars, &item->decl, *nr_vars); (*nr_vars)++; break; case JAF_STMT_LABELED: @@ -397,7 +398,7 @@ static void function_init_vars(struct ain *ain, struct ain_function *f, struct j assert(decl->params->items[i]->kind == JAF_DECLARATION); assert(decl->params->items[i]->decl.name); struct jaf_declaration *param = &decl->params->items[i]->decl; - init_variable(ain, &f->vars[i], param->name, param->type); + init_variable(ain, &f->vars[i], param, i); } f->vars = block_get_vars(ain, decl->body, f->vars, &f->nr_vars); } diff --git a/src/tools/ainedit/jaf_types.c b/src/tools/ainedit/jaf_types.c index a5c4c65..bf84130 100644 --- a/src/tools/ainedit/jaf_types.c +++ b/src/tools/ainedit/jaf_types.c @@ -78,6 +78,21 @@ static enum jaf_type jaf_merge_types(enum jaf_type a, enum jaf_type b) ERROR("Incompatible types"); } +static void jaf_check_types_lvalue(struct jaf_env *env, struct jaf_expression *e) +{ + // TODO: array subscripts + if (e->type != JAF_EXP_IDENTIFIER && e->type != JAF_EXP_MEMBER) + ERROR("Invalid expression as lvalue"); + switch (e->value_type.type) { + case JAF_INT: + case JAF_FLOAT: + case JAF_STRING: + break; + default: + ERROR("Invalid type as lvalue"); + } +} + static void jaf_check_types_unary(struct jaf_env *env, struct jaf_expression *expr) { jaf_derive_types(env, expr->expr); @@ -105,6 +120,7 @@ static void jaf_check_types_binary(struct jaf_env *env, struct jaf_expression *e { jaf_derive_types(env, expr->lhs); jaf_derive_types(env, expr->rhs); + switch (expr->op) { // real ops case JAF_MULTIPLY: @@ -153,7 +169,11 @@ static void jaf_check_types_binary(struct jaf_env *env, struct jaf_expression *e case JAF_XOR_ASSIGN: case JAF_OR_ASSIGN: case JAF_REF_ASSIGN: - ERROR("Assignment expressions not supported"); + jaf_check_types_lvalue(env, expr->lhs); + // FIXME: need to coerce types (?) + jaf_check_type(expr->rhs, &expr->lhs->value_type); + expr->value_type.type = expr->lhs->value_type.type; + break; default: ERROR("Unhandled binary operator"); }