Exemple #1
0
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);
}
Exemple #2
0
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;
}
Exemple #3
0
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);
}
Exemple #4
0
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;
}
Exemple #5
0
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;
}
Exemple #6
0
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;
}
Exemple #7
0
// 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);
  }
}
Exemple #8
0
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;
}
Exemple #9
0
/* 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';
	}
}
Exemple #10
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();
  }
}
Exemple #11
0
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;
}
Exemple #12
0
//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);
		}
	}
}
Exemple #13
0
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);
	}
}
Exemple #14
0
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);
    }
}
Exemple #15
0
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);
}
Exemple #16
0
value_t assembler_lookup_symbol(assembler_t *assm, value_t symbol,
    binding_info_t *info_out) {
  return scope_lookup(assm->scope, symbol, info_out);
}
Exemple #17
0
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;
}
Exemple #18
0
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;
}
Exemple #19
0
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");
  }
}
Exemple #20
0
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;
}
Exemple #21
0
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;
}