void expr_resolve( struct expr *e ) { if (!e) return; expr_resolve(e->left); expr_resolve(e->right); if (e->kind == EXPR_NAME) { struct symbol *s = scope_lookup(e->name); if (s) { e->symbol = s; printf("%s resovles to ", e->name ); symbol_print( s ); printf("\n"); } else { printf("variable %s not defined\n", e->name); exit(1); } } if (e->kind == EXPR_FUNCTION_VAL) { struct symbol *s = scope_lookup(e->name); if (s) { e->symbol = s; printf("%s resovles to ", e->name ); symbol_print( s ); printf("\n"); } else { printf("variable function %s not defined\n", e->name); exit(1); } } expr_resolve(e->next); }
static value_t lambda_scope_lookup(lambda_scope_o *self, value_t symbol, binding_info_t *info_out) { size_t capture_count_before = get_array_buffer_length(self->captures); // See if we've captured this variable before. for (size_t i = 0; i < capture_count_before; i++) { value_t captured = get_array_buffer_at(self->captures, i); if (value_identity_compare(captured, symbol)) { // Found it. Record that we did if necessary and return success. if (info_out != NULL) binding_info_set(info_out, btLambdaCaptured, i, 0); return success(); } } // We haven't seen this one before so look it up outside. value_t value = scope_lookup(self->outer, symbol, info_out); if (info_out != NULL && !in_condition_cause(ccNotFound, value)) { // We found something and this is a read. Add it to the list of captures. runtime_t *runtime = self->assembler->runtime; if (get_array_buffer_length(self->captures) == 0) { // The first time we add something we have to create a new array buffer // since all empty capture scopes share the singleton empty buffer. TRY_SET(self->captures, new_heap_array_buffer(runtime, 2)); } TRY(add_to_array_buffer(runtime, self->captures, symbol)); binding_info_set(info_out, btLambdaCaptured, capture_count_before, 0); } return value; }
void decl_typecheck( struct decl *d ) { if (!d) return; if (d->value) { struct type *T = expr_typecheck( d-> value ); if (!type_compare(d->type, T)) { printf("type error: cannot initialize variable (%s) of type ", d->name); type_print(d->type); printf(" and assign it a "); type_print( T ); printf("\n"); } } if (d->type->kind == TYPE_ARRAY) { // for array decl_array_typecheck(d->type, d->name); } else if (d->type->kind == TYPE_FUNCTION) { // for function return decl_array_typecheck(d->type->subtype, d->name); } if (d->code) { decl_func_sym = scope_lookup(d->name); stmt_typecheck(d->code); } if (d->next) decl_typecheck(d->next); }
int check_func_call(is_func_call* node) { is_expr_list* arg; int errors = 0; int i; char *typeA, *typeB; node->symbol = scope_lookup(symtab, node->id->name, t_symbol_func); if (!node->symbol) { pretty_error(node->line, "undefined function \"%s\"", node->id->name); errors++; } else { errors += check_func_call_arg_list(node->args); if (errors == 0) { if ((node->args == NULL && node->symbol->data.func_data.nArgs != 0) || (node->args != NULL && node->args->length != node->symbol->data.func_data.nArgs)) { pretty_error(node->line, "too %s arguments for \"%s\", got %d expected %d (declaration is here: %d)", node->args->length > node->symbol->data.func_data.nArgs ? "many" : "few", node->id->name, node->args->length, node->symbol->data.func_data.nArgs, node->symbol->line); errors++; } else { for (i = 0, arg = node->args; arg != NULL; i++, arg = arg->next) { if (!type_type_assign_able(node->symbol->data.func_data.args[i]->type, arg->node->s_type)) { errors++; pretty_error(node->line, "invalid parameter \"%d\" (%s) of function %s (got %s expected %s)", i, node->symbol->data.func_data.args[i]->id->name, node->id->name, typeA = string_type_decl(arg->node->s_type), typeB = string_type_decl(node->symbol->data.func_data.args[i]->type) ); free(typeA); free(typeB); } } if (errors == 0) node->s_type = duplicate_type_decl(node->symbol->data.func_data.type); } } } return errors; }
SYMBOL* scope_local_lookup(SCOPE* scope, char *id, type_symbol type) { SYMBOL* symbol = NULL; symbol = symbol_lookup(scope->node[type], id); if (!symbol && scope->parent && !scope->parent->global) return scope_lookup(scope->parent, id, type); return symbol; }
static value_t block_scope_lookup(block_scope_o *self, value_t symbol, binding_info_t *info_out) { // Look up outside this scope. value_t value = scope_lookup(self->outer, symbol, info_out); if (info_out != NULL && !in_condition_cause(ccNotFound, value)) // If we found a binding refract it increasing the block depth but otherwise // leaving the binding as it is. info_out->block_depth++; return value; }
// Performs a lookup for a single symbol scope. static value_t single_symbol_scope_lookup(single_symbol_scope_o *self, value_t symbol, binding_info_t *info_out) { if (value_identity_compare(symbol, self->symbol)) { if (info_out != NULL) *info_out = self->binding; return success(); } else { return scope_lookup(self->outer, symbol, info_out); } }
SYMBOL* scope_lookup(SCOPE* scope, char *id) { SYMBOL* symbol = NULL; symbol = symbol_lookup(scope->node, id); if (!symbol && scope->parent) return scope_lookup(scope->parent, id); return symbol; }
/* return class of last character */ static char output_token(const yystype *token, struct scope *scope, struct buf *out, char lastchar) { char sbuf[128]; const char *s = TOKEN_GET(token, cstring); /* TODO: use a local buffer, instead of FILE* */ switch(token->type) { case TOK_StringLiteral: output_space(lastchar,'"', out); buf_outc('"', out); if(s) { buf_outs(s, out); } buf_outc('"', out); return '\"'; case TOK_NumericInt: output_space(lastchar,'0', out); snprintf(sbuf, sizeof(sbuf), "%ld", TOKEN_GET(token, ival)); buf_outs(sbuf, out); return '0'; case TOK_NumericFloat: output_space(lastchar,'0', out); snprintf(sbuf, sizeof(sbuf), "%g", TOKEN_GET(token, dval)); buf_outs(sbuf, out); return '0'; case TOK_IDENTIFIER_NAME: output_space(lastchar,'a', out); if(s) { long id = scope_lookup(scope, s, strlen(s)); if(id == -1) { /* identifier not normalized */ buf_outs(s, out); } else { snprintf(sbuf, sizeof(sbuf), "n%03ld",id); buf_outs(sbuf, out); } } return 'a'; case TOK_FUNCTION: output_space(lastchar,'a', out); buf_outs("function",out); return 'a'; default: if(s) { const size_t len = strlen(s); output_space(lastchar,s[0], out); buf_outs(s, out); return len ? s[len-1] : '\0'; } return '\0'; } }
// Performs a lookup for a single symbol scope. static value_t map_scope_lookup(map_scope_o *self, value_t symbol, binding_info_t *info_out) { value_t value = get_id_hash_map_at(self->map, symbol); if (in_condition_cause(ccNotFound, value)) { return scope_lookup(self->outer, symbol, info_out); } else { if (info_out != NULL) { binding_info_codec_t codec; codec.encoded = get_integer_value(value); *info_out = codec.decoded; } return success(); } }
int check_class_def(is_class_def* node) { int errors = 0; SYMBOL* symbol; symbol = scope_lookup(symtab, node->id->name, t_symbol_class); if (symbol) { errors++; pretty_error(node->line, "class \"%s\" is already defined (previous declaration was here: %d)", node->id->name, symbol->line); } else scope_insert(symtab, symbol = symbol_new_class(node->id->name, node->line)); node->scope = scope_new(symbol, true); /* FIXME: this should be in application and not in class def, because theoretically class should be able to access other classes */ scope_push(node->scope); errors += check_class_stmt_list(node->body, true); if (errors == 0) { symbol = scope_lookup(symtab, "main", t_symbol_func); if (!symbol) { errors++; pretty_error(node->line, "missing main entry point"); } } errors += check_class_stmt_list(node->body, false); scope_pop(); return errors; }
//Resolves the name of an expression void expr_resolve(struct expr *e){ if(!e) return; expr_resolve(e->left); expr_resolve(e->right); if(e->kind == EXPR_IDENT) { e->symbol = scope_lookup(e->name); if(e->symbol) { printf("%s resolves to "); symbol_print(e->symbol); } else { //not defined in this scope e->symbol = 0; resolve_error(e->name); } } }
void expr_resolve (struct expr *e, int quiet) { if(!e) return; expr_resolve(e->left, quiet); expr_resolve(e->right, quiet); if(e->kind == EXPR_NAME) { struct symbol *s = scope_lookup(e->name); if(s) { e->symbol = s; if(!quiet) printf("Found use of symbol %s\n", e->name); } else { if(!quiet) printf("Unfound identifier: %s\n", e->name); exit(1); } } else if(e->kind == EXPR_STRING) { push_string_front(e->string_literal); } }
void expr_resolve(struct expr *e) { if (!e) return; expr_resolve(e->left); expr_resolve(e->right); if (e->kind == EXPR_VARIABLE || e->kind == EXPR_FUNCTION_CALL) { struct symbol *s = scope_lookup(e->name); if (s) { e->symbol = s; printf("%s resolves to %s %d\n", e->name, symbol_kind_to_string(e->symbol->kind), e->symbol->which); } else { printf("variable %s not found\n", e->name); error_count++; } expr_resolve(e->right); } }
void expr_resolve(struct expr *e){ if (e == NULL) { return; } expr_resolve(e->left); expr_resolve(e->right); if (e->kind==EXPR_IDENTIFIER){ struct symbol *s = scope_lookup(e->name); if (s != NULL){ e->symbol = s; char *this_variable = malloc(sizeof(char) * 10); switch (s->kind){ case SYMBOL_LOCAL: sprintf(this_variable,"LOCAL %i",s->which); break; case SYMBOL_GLOBAL: sprintf(this_variable,"GLOBAL %i",s->which); break; case SYMBOL_PARAM: sprintf(this_variable,"PARAM %i",s->which); break; default: fprintf(stderr,"Scope not recognized for symbol: %s\n",e->name); error_counter += 1; break; } printf("%s resolved to %s\n",e->name,this_variable); } else { fprintf(stderr,"Symbol %s not declared\n",e->name); error_counter += 1; } } expr_resolve(e->next); }
value_t assembler_lookup_symbol(assembler_t *assm, value_t symbol, binding_info_t *info_out) { return scope_lookup(assm->scope, symbol, info_out); }
int check_func_def(is_func_def* node, bool first_pass) { SYMBOL* symbol; SCOPE* tempscope; int label; int errors = 0; is_type_decl *tmpType = NULL; if (first_pass) { errors += check_type_decl(node->type); symbol = scope_lookup(symtab, node->id->name, t_symbol_func); if (symbol) { pretty_error(node->line, "symbol \"%s\" is already defined (previous declaration was here: %d)", node->id->name, symbol->line); errors++; } else { tempscope = scope_new(NULL, false); scope_push(tempscope); errors += check_func_def_args(node->args); scope_pop(); if (strcmp(node->id->name, "main") == 0) { label = 0; if (node->args) /* no args is valid */ { if (node->args->length == 1) /* main may must not have more than two arguments */ { tmpType = insert_type_decl_array(insert_array_decl(insert_type_object(t_type_native_string), new_dims_empty_list(0, 1))); /* must be an array of Strings */ if (!type_type_equal(tmpType,node->args->node->type)) { errors++; pretty_error(node->line, "main function arguments do not match any valid prototypes"); } free_type_decl(tmpType); } else { errors++; pretty_error(node->line, "main function arguments do not match any valid prototypes"); } } tmpType = insert_type_decl_object(insert_type_object(t_type_native_int)); /* return value must be int or void */ if (!type_type_equal(tmpType,node->type)) { free_type_decl(tmpType); tmpType = new_type_decl_void(0); /* check for void */ if (!type_type_equal(tmpType,node->type)) /* none; errors occurred */ { errors++; pretty_error(node->line, "main function return type does not match any valid types (nor int nor void)"); } } free_type_decl(tmpType); } else label = ++label_counter; symbol = symbol_new_func(node->id->name, node->line, node->type, node->args, label); scope_delete(tempscope); scope_insert(symtab, symbol); node->scope = scope_new(symbol, false); } } else { scope_push(node->scope); errors += check_func_def_args(node->args); /* this will not give errors */ errors += check_stmt_list(node->body); if ((!node->body || !node->body->terminated) && !(node->type->type == t_type_decl_type_object && node->type->data.type_object->type == t_type_native_void)) { pretty_error(node->line, "reached end of non void function"); errors++; } scope_pop(); } return errors; }
int check_assign_op(is_assign_op* node) { int errors = 0; char* typeA, *typeB; is_type_native type; SYMBOL* symbol; errors += check_var(node->var); errors += check_expr(node->expr); if (errors == 0) { switch (node->type) { case t_assign_op_eq: if (!type_type_assign_able(node->var->s_type, node->expr->s_type)) { errors++; pretty_error(node->line, "invalid assignment from %s to %s", typeA = string_type_decl(node->expr->s_type), typeB = string_type_decl(node->var->s_type) ); free(typeA); free(typeB); } else { if (node->var->type == t_var_id) { symbol = scope_lookup(symtab, node->var->data.id->name, t_symbol_var); symbol->data.var_data.initialized = true; } node->s_type = duplicate_type_decl(node->var->s_type); } break; default: if (node->var->s_type->type == t_type_decl_array_decl || node->expr->s_type->type == t_type_decl_array_decl) { errors++; pretty_error(node->line, "assignment operations are invalid between array types"); } else { type = operators_binary[node->type][node->var->s_type->data.type_object->type][node->expr->s_type->data.type_object->type]; if (type == ERROR) { errors++; pretty_error(node->line, "assignment operation invalid between %s and %s", typeA = string_type_decl(node->var->s_type), typeB = string_type_decl(node->expr->s_type) ); free(typeA); free(typeB); } else node->s_type = insert_type_decl_object(insert_type_object(type)); } break; } } return errors; }
expr *eval(scope *scope, expr *e) { if (e == NULL) return NULL; switch (e->type) { // String and Integer expressions evaluate to themselves. case STRING_EXPR: case INT_EXPR: case FUNC_EXPR: case BUILTIN_EXPR: case BOOL_EXPR: return e; case SYMBOL_EXPR: { expr *value = scope_lookup(scope, e->string_value); // if (!value) // PANIC("Symbol %s not bound to any value\n", e->string_value); return value; } case CELL_EXPR: { expr *head = eval(scope, e->head); if (head == NULL) PANIC("() is not a function."); if (head->type == BUILTIN_EXPR) { // Call the built-in construct. return head->func_ptr(scope, e->tail); } else if (head->type == FUNC_EXPR) { // Call the function. struct scope *new_scope = scope_create(head->closure); if (islist(head->arguments)) { expr *actuals = e->tail; for (expr *formal = head->arguments; formal != NULL; formal = formal->tail) { expr *formal_expr = formal->head; assert(formal_expr->type == SYMBOL_EXPR); if (actuals != NULL) { // If this is a regular function, evaluate the argument. Otherwise, return expression, // Since macros take in their arguments literally. expr *actual_value = head->ismacro ? actuals->head : eval(scope, actuals->head); // Bind the actual value to the formal symbol. scope_add_mapping(new_scope, formal_expr->string_value, actual_value); // Proceed to the next actual. actuals = actuals->tail; } else { // No more actuals, so simply bind the symbol to the empty list (NIL). scope_add_mapping(new_scope, formal_expr->string_value, NULL); } } } else if (issymbol(head->arguments)) { if (head->ismacro) scope_add_mapping(new_scope, head->arguments->string_value, e->tail); else scope_add_mapping(new_scope, head->arguments->string_value, eval_varargs(scope, e->tail)); } // Evaulate the body of the function struct expr *last_value = NULL; for (struct expr *statement = head->body; statement != NULL; statement = statement->tail) { last_value = eval(new_scope, statement->head); } // If this is a regular function, we simply return the result. return head->ismacro ? eval(scope, last_value) : last_value; } else { PANIC("Tried to execute something which is not a function or a macro."); } } default: PANIC("Unkown expression type.\n"); } }
int check_var(is_var* node) { int errors = 0; char *typeA; switch (node->type) { case t_var_id: node->symbol = scope_lookup(symtab, node->data.id->name, t_symbol_var); if (!node->symbol) { errors++; pretty_error(node->line, "undefined variable \"%s\"", node->data.id->name); node->initialized = false; } else { node->initialized = node->symbol->data.var_data.initialized; node->s_type = duplicate_type_decl(node->symbol->data.var_data.type); } break; case t_var_new_op: errors += check_new_op(node->data.new_op); node->s_type = duplicate_type_decl(node->data.new_op->s_type); node->initialized = true; break; case t_var_array: errors += check_var(node->data.array.var); errors += check_dims_sized(node->data.array.dims); if (errors == 0) { if (node->data.array.var->s_type->type == t_type_decl_array_decl) { node->s_type = decapsulate_type_decl(node->data.array.var->s_type); } else { errors++; pretty_error(node->line, "subscript of unsuscriptable type (%s)", typeA = string_type_decl(node->data.array.var->s_type) ); free(typeA); } } node->initialized = true; break; case t_var_func_call: errors += check_func_call(node->data.func_call.call); errors += check_dims_sized(node->data.array.dims); if (errors == 0) { if (node->data.func_call.call->s_type->type == t_type_decl_array_decl) { node->s_type = decapsulate_type_decl(node->data.func_call.call->s_type); } else { errors++; pretty_error(node->line, "subscript of unsuscriptable type (%s)", typeA = string_type_decl(node->data.func_call.call->s_type) ); free(typeA); } } node->initialized = true; break; } /* todo propagate node->initialized */ return errors; }
struct param_list * param_list_copy(struct param_list *p){ if(!p) return NULL; struct param_list * temp = param_list_create(p->name, type_copy(p->type), param_list_copy(p->next)); temp->symbol = scope_lookup(p->name); return temp; }