/* the effect of pointer indirection */ typeID ptrdown (typeID t) { int *tt = open_typeID (t), *tn; if (tt [1] != '*' && tt [1] != '[') expr_error ("* not applicable"); tn = allocaint (intlen (tt)); tn [0] = tt [0]; intcpy (tn + 1, tt + 2); return enter_type (tn); }
/* given a function type return the return type */ typeID funcreturn (typeID t) { int *tt = open_typeID (t), *tn, i; if (tt [1] != '(') expr_error ("bug: request return type of no function"); for (i = 2; tt [i] != INTERNAL_ARGEND; i++); tn = allocaint (intlen (&tt [i]) + 2); tn [0] = tt [0]; intcpy (tn + 1, tt + i + 1); return enter_type (tn); }
/* take a function type and add the first rec* argument */ typeID makemember (typeID t, recID r) { int *tt = open_typeID (t), *tn; if (tt [1] != '(') expr_error ("bug: request to makemember on no function"); tn = allocaint (intlen (tt) + 4); tn [0] = tt [0]; tn [1] = '('; tn [2] = pthis_of_struct (r); intcpy (tn + 3, tt + 2); return enter_type (tn); }
static Eina_Bool eval_exp(const Eolian_Expression *expr, Eolian_Expression_Mask mask, Eolian_Expression *out) { switch (expr->type) { case EOLIAN_EXPR_INT: case EOLIAN_EXPR_LONG: case EOLIAN_EXPR_LLONG: { if (!(mask & EOLIAN_MASK_SINT)) return expr_type_error(expr, EOLIAN_MASK_SINT, mask); *out = *expr; return EINA_TRUE; } case EOLIAN_EXPR_UINT: case EOLIAN_EXPR_ULONG: case EOLIAN_EXPR_ULLONG: { if (!(mask & EOLIAN_MASK_UINT)) return expr_type_error(expr, EOLIAN_MASK_UINT, mask); *out = *expr; return EINA_TRUE; } case EOLIAN_EXPR_FLOAT: case EOLIAN_EXPR_DOUBLE: { if (!(mask & EOLIAN_MASK_FLOAT)) return expr_type_error(expr, EOLIAN_MASK_FLOAT, mask); *out = *expr; return EINA_TRUE; } case EOLIAN_EXPR_STRING: { if (!(mask & EOLIAN_MASK_STRING)) return expr_type_error(expr, EOLIAN_MASK_STRING, mask); *out = *expr; return EINA_TRUE; } case EOLIAN_EXPR_NULL: { if (!(mask & EOLIAN_MASK_NULL)) return expr_type_error(expr, EOLIAN_MASK_NULL, mask); *out = *expr; return EINA_TRUE; } case EOLIAN_EXPR_CHAR: { if (!(mask & EOLIAN_MASK_CHAR)) return expr_type_error(expr, EOLIAN_MASK_CHAR, mask); *out = *expr; return EINA_TRUE; } case EOLIAN_EXPR_BOOL: { if (!(mask & EOLIAN_MASK_BOOL)) return expr_type_error(expr, EOLIAN_MASK_BOOL, mask); *out = *expr; return EINA_TRUE; } case EOLIAN_EXPR_NAME: { const Eolian_Variable *var = eolian_variable_constant_get_by_name (expr->value.s); const Eolian_Expression *exp = NULL; if (!var) { const Eolian_Type *etp; const Eolian_Enum_Type_Field *fl; /* try aliases, hoping it'll be enum */ char *fulln = NULL, *memb = NULL; if (!split_enum_name(expr->value.s, &fulln, &memb)) return expr_error(expr, "undefined variable"); /* assert int here, as we're clearly dealing with enum */ if (!(mask & EOLIAN_MASK_INT)) return expr_type_error(expr, EOLIAN_MASK_INT, mask); etp = eolian_type_alias_get_by_name(fulln); while (etp && (etp->type == EOLIAN_TYPE_ALIAS || etp->type == EOLIAN_TYPE_REGULAR)) etp = eolian_type_base_type_get(etp); if (!etp) etp = eolian_type_enum_get_by_name(fulln); if (!etp || etp->type != EOLIAN_TYPE_ENUM) { free(fulln); return expr_error(expr, "undefined variable"); } fl = eolian_type_enum_field_get(etp, memb); if (fl) exp = eolian_type_enum_field_value_get(fl, EINA_TRUE); free(fulln); if (!exp) return expr_error(expr, "invalid enum field"); } else exp = var->value; if (!exp) return expr_error(expr, "undefined variable"); return eval_exp(exp, mask, out); } case EOLIAN_EXPR_UNARY: return eval_unary(expr, mask, out); case EOLIAN_EXPR_BINARY: return eval_binary(expr, mask, out); default: assert(EINA_FALSE); return EINA_FALSE; } return EINA_TRUE; }
ast_result_t pass_expr(ast_t** astp, pass_opt_t* options) { typecheck_t* t = &options->check; ast_t* ast = *astp; bool r = true; switch(ast_id(ast)) { case TK_NOMINAL: r = expr_nominal(options, astp); break; case TK_FVAR: case TK_FLET: case TK_PARAM: r = expr_field(options, ast); break; case TK_NEW: case TK_BE: case TK_FUN: r = expr_fun(options, ast); break; case TK_SEQ: r = expr_seq(ast); break; case TK_VAR: case TK_LET: r = expr_local(t, ast); break; case TK_BREAK: r = expr_break(t, ast); break; case TK_CONTINUE: r = expr_continue(t, ast); break; case TK_RETURN: r = expr_return(options, ast); break; case TK_IS: case TK_ISNT: r = expr_identity(options, ast); break; case TK_ASSIGN: r = expr_assign(options, ast); break; case TK_CONSUME: r = expr_consume(t, ast); break; case TK_RECOVER: r = expr_recover(ast); break; case TK_DOT: r = expr_dot(options, astp); break; case TK_TILDE: r = expr_tilde(options, astp); break; case TK_QUALIFY: r = expr_qualify(options, astp); break; case TK_CALL: r = expr_call(options, astp); break; case TK_IF: r = expr_if(options, ast); break; case TK_WHILE: r = expr_while(options, ast); break; case TK_REPEAT: r = expr_repeat(options, ast); break; case TK_TRY_NO_CHECK: case TK_TRY: r = expr_try(options, ast); break; case TK_MATCH: r = expr_match(options, ast); break; case TK_CASES: r = expr_cases(ast); break; case TK_CASE: r = expr_case(options, ast); break; case TK_TUPLE: r = expr_tuple(ast); break; case TK_ARRAY: r = expr_array(options, astp); break; case TK_REFERENCE: r = expr_reference(options, astp); break; case TK_THIS: r = expr_this(options, ast); break; case TK_TRUE: case TK_FALSE: r = expr_literal(options, ast, "Bool"); break; case TK_ERROR: r = expr_error(ast); break; case TK_COMPILER_INTRINSIC: r = expr_compiler_intrinsic(t, ast); break; case TK_POSITIONALARGS: case TK_NAMEDARGS: case TK_NAMEDARG: case TK_UPDATEARG: ast_inheritflags(ast); break; case TK_AMP: r = expr_addressof(options, ast); break; case TK_DONTCARE: r = expr_dontcare(ast); break; case TK_INT: // Integer literals can be integers or floats make_literal_type(ast); break; case TK_FLOAT: make_literal_type(ast); break; case TK_STRING: if(ast_id(ast_parent(ast)) == TK_PACKAGE) return AST_OK; r = expr_literal(options, ast, "String"); break; case TK_FFICALL: return expr_ffi(options, ast); default: {} } if(!r) { assert(get_error_count() > 0); return AST_ERROR; } // Can't use ast here, it might have changed symtab_t* symtab = ast_get_symtab(*astp); if(symtab != NULL && !symtab_check_all_defined(symtab)) return AST_ERROR; return AST_OK; }