cx_int16 Fast_Member_resolveMember(Fast_Member _this, cx_type type, cx_string member) { cx_object o = NULL; if (cx_instanceof(cx_type(cx_interface_o), type) && !strcmp(member, "super")) { if (cx_interface(type)->base) { _this->member = NULL; cx_set(&Fast_Expression(_this)->type, cx_interface(type)->base); } else { cx_id id; Fast_Parser_error(yparser(), "type '%s' has no base", Fast_Parser_id(type, id)); goto error; } } else { if (cx_instanceof(cx_type(cx_interface_o), type)) { o = cx_interface_resolveMember(cx_interface(type), member); } if (!o) { /* If no members are found for name, look for methods */ o = cx_type_resolveProcedure(type, member); if (!o) { cx_id id; Fast_Parser_error(yparser(), "unresolved member '%s' for type '%s'", member, Fast_Parser_id(type, id)); goto error; } cx_set(&Fast_Expression(_this)->type, cx_function(o)->returnType); } else { cx_set(&Fast_Expression(_this)->type, cx_member(o)->type); } _this->member = o; cx_keep_ext(_this, o, "Keep object for member-expression"); } return 0; error: return -1; }
/* Create if statement based on ternary operator expressions */ ast_If ast_Ternary_createIf(ast_Expression condition, ast_Node ifTrue, ast_Node ifFalse) { ast_Block trueBlock; ast_Block falseBlock; ast_If falseIf; ast_If result; if (corto_instanceof(corto_type(ast_Block_o), ifTrue)) { trueBlock = ast_BlockCreate(yparser()->block); falseBlock = ast_BlockCreate(yparser()->block); ast_Block_addStatement(trueBlock, ast_Node(ifTrue)); ast_Block_addStatement(falseBlock, ast_Node(ifFalse)); ast_Parser_collect(yparser(), trueBlock); ast_Parser_collect(yparser(), falseBlock); } else { trueBlock = ast_Block(ifTrue); falseBlock = ast_Block(ifFalse); } falseIf = ast_IfCreate(NULL, falseBlock, NULL); result = ast_IfCreate(condition, trueBlock, falseIf); /* Because a ternary operator always has a true and false branch it there is not much use * in reporting unreachable code. If a ternary operator has a compile-time resolvable * condition, it is probably intended. */ ast_If_noWarnUnreachable(result); ast_Parser_collect(yparser(), falseIf); return result; }
/* ::cortex::Fast::StaticInitializer::value(Expression v) */ cx_int16 Fast_StaticInitializer_value(Fast_StaticInitializer _this, Fast_Expression v) { /* $begin(::cortex::Fast::StaticInitializer::value) */ cx_word offset; cx_uint32 variable; cx_uint32 fp = Fast_Initializer(_this)->fp; cx_type type = Fast_Initializer_currentType(Fast_Initializer(_this)); cx_type vType = Fast_Expression_getType_type(v, type); if (!type) { cx_id id; Fast_Parser_error(yparser(), "excess elements in initializer of type '%s'", Fast_Parser_id(Fast_Object(Fast_Expression(_this)->type)->value, id)); goto error; } if (!vType) { goto error; } /* Validate whether expression type matches current type of initializer */ if (vType && !cx_type_castable(type, vType)) { cx_id id, id2; Fast_Parser_error(yparser(), "type '%s' invalid here (expected '%s')", Fast_Parser_id(vType, id), Fast_Parser_id(type, id2)); goto error; } /* Validate whether value has no side-effects - which are not allowed in a static initializer */ if (Fast_Expression_hasSideEffects(v)) { Fast_Parser_error(yparser(), "expressions with side-effects are not allowed in static initializers."); goto error; } /* Serialize value to all variables being initialized */ for(variable=0; variable<Fast_Initializer(_this)->variableCount; variable++) { /* Calculate the offset for the current value */ _this->frames[fp].ptr[variable] = Fast_Initializer_offset(_this, variable); offset = _this->frames[fp].ptr[variable]; if (!offset) { goto error; } if (Fast_Expression_serialize(v, type, offset)) { goto error; } } return Fast_Initializer_next(Fast_Initializer(_this)); error: return -1; /* $end */ }
/* Walk embedded expressions in string */ cx_int16 Fast_String_parse(Fast_String _this) { cx_char *ptr, ch, *str; Fast_String element; ptr = _this->value; str = ptr; /* Keep track of beginning of string-element */ if (ptr) { /* Walk string, split embedded expressions */ while((ch = *ptr)) { switch(ch) { case '$': /* Insert string-element */ if (str != ptr) { *ptr = '\0'; element = Fast_String__create(str); cx_llAppend(_this->elements, element); *ptr = ch; } /* Parse embedded expression */ str = ptr = Fast_String_parseEmbedded(_this, ptr+1); if (!ptr) { yparser()->line = Fast_Node(_this)->line; yparser()->column = Fast_Node(_this)->column; Fast_Parser_error(yparser(), "parsing string '%s' failed", _this->value); goto error; } break; default: ptr++; break; } } /* If string contains embedded expressions, add last bit of remaining * string to elements list */ if ((str != _this->value) && *str) { element = Fast_String__create(str); cx_llAppend(_this->elements, element); } } else { element = Fast_String__create("null"); cx_llAppend(_this->elements, element); } return 0; error: return -1; }
/* ::cortex::Fast::String::construct() */ cx_int16 Fast_String_construct(Fast_String _this) { /* $begin(::cortex::Fast::String::construct) */ if (!yparser()->block || !yparser()->scope) { goto error; } _this->block = yparser()->block; cx_keep_ext(_this, _this->block, "_this->block (keep block for string-expression)"); _this->scope = yparser()->scope; cx_keep_ext(_this, _this->scope, "_this->scope (keep scope for string-expression)"); return 0; error: return -1; /* $end */ }
/* ::cortex::Fast::Expression::fromList(list{Expression} list) */ Fast_Expression Fast_Expression_fromList(Fast_Expression_list list) { /* $begin(::cortex::Fast::Expression::fromList) */ Fast_Expression result = NULL; /* Convert list to comma expression */ if (list) { if (cx_llSize(list) == 1) { result = cx_llGet(list, 0); } else { cx_ll toList = cx_llNew(); /* Copy list */ cx_iter iter; Fast_Expression expr; result = Fast_Expression(Fast_Comma__create()); iter = cx_llIter(list); while(cx_iterHasNext(&iter)) { expr = cx_iterNext(&iter); cx_llAppend(toList, expr); cx_keep_ext(result, expr, "add expression from list to comma-expression"); } Fast_Comma(result)->expressions = toList; Fast_Parser_collect(yparser(), result); } } return result; /* $end */ }
/* ::cortex::Fast::String::serialize(type dstType,word dst) */ cx_int16 Fast_String_serialize(Fast_String _this, cx_type dstType, cx_word dst) { /* $begin(::cortex::Fast::String::serialize) */ Fast_valueKind kind; kind = Fast_valueKindFromType(dstType); switch(kind) { case Fast_Bool: case Fast_Int: case Fast_SignedInt: case Fast_Text: cx_convert(cx_primitive(cx_string_o), &_this->value, cx_primitive(dstType), (void*)dst); break; case Fast_Ref: { cx_object o = cx_resolve_ext(NULL, NULL, _this->value, FALSE, "Serialize reference from string"); cx_set_ext(NULL, &dst, o, "serialize string to reference"); break; } default: { cx_id id; Fast_Parser_error(yparser(), "cannot serialize string value to storage of type '%s'", Fast_Parser_id(dstType, id)); goto error; break; } } return 0; error: return -1; /* $end */ }
/* Create a call-expression */ Fast_Call Fast_createCallWithArguments(Fast_Expression instance, cx_string function, Fast_Expression arguments) { Fast_Call result; Fast_CallBuilder builder; /* Initialize builder */ Fast_CallBuilder__init(&builder, function, arguments, instance, yparser()->scope, yparser()->block); result = Fast_CallBuilder_build(&builder); Fast_CallBuilder__deinit(&builder); return result; }
/* $header(::cortex::Fast::Expression::getType_expr) */ cx_type Fast_Expression_getType_intern(Fast_Expression _this, cx_type target, Fast_Expression targetExpr) { cx_type result = Fast_Expression_getType(_this); if (!result) { if ((Fast_Node(_this)->kind == Fast_LiteralExpr) && (Fast_Literal(_this)->kind == Fast_Nothing)) { if (target) { if (target->reference) { result = target; } else if ((target->kind == CX_PRIMITIVE) && (cx_primitive(target)->kind == CX_TEXT)) { result = cx_type(cx_string_o); } else { if (targetExpr && targetExpr->isReference) { result = target; } else { goto error; } } } else { goto error; } } else if (Fast_Node(_this)->kind == Fast_InitializerExpr) { result = target; } else { goto error; } } else if ((target && (target->kind == CX_VOID) && target->reference)) { result = cx_object_o; } return result; error: Fast_Parser_error(yparser(), "inconsistent usage of references"); return NULL; }
/* ::cortex::Fast::SignedInteger::serialize(type dstType,word dst) */ cx_int16 Fast_SignedInteger_serialize(Fast_SignedInteger _this, cx_type dstType, cx_word dst) { /* $begin(::cortex::Fast::SignedInteger::serialize) */ Fast_valueKind kind; kind = Fast_valueKindFromType(dstType); memset((void*)dst, 0, cx_type_sizeof(dstType)); switch(kind) { case Fast_Bool: *(cx_bool*)dst = _this->value ? TRUE : FALSE; break; case Fast_Int: case Fast_SignedInt: case Fast_Enum: case Fast_Text: cx_convert(cx_primitive(cx_int64_o), &_this->value, cx_primitive(dstType), (void*)dst); break; default: { cx_id id; Fast_Parser_error(yparser(), "cannot serialize signed integer value to storage of type '%s'", Fast_Parser_id(dstType, id)); goto error; break; } } return 0; error: return -1; /* $end */ }
Fast_Call Fast_createCallFromExpr(Fast_Expression f, Fast_Expression arguments) { Fast_Call result = NULL; Fast_Expression instance = NULL; cx_id name; cx_object scope = yparser()->scope; Fast_CallBuilder builder; if (Fast_Node(f)->kind == Fast_StorageExpr) { switch(Fast_Storage(f)->kind) { case Fast_ObjectStorage: { cx_object o = Fast_Object(f)->value; cx_signatureName(cx_nameof(o), name); scope = cx_parentof(o); break; } case Fast_LocalStorage: strcpy(name, Fast_Local(f)->name); break; case Fast_MemberStorage: instance = Fast_Member(f)->lvalue; strcpy(name, Fast_String(Fast_Member(f)->rvalue)->value); break; case Fast_ElementStorage: result = Fast_Call(Fast_DelegateCall__create(NULL, arguments, f)); break; default: Fast_Parser_error(yparser(), "'%s' expression is not callable", cx_nameof(cx_enum_constant(Fast_storageKind_o, Fast_Storage(f)->kind))); goto error; } } if (!result) { Fast_CallBuilder__init(&builder, name, arguments, instance, scope, yparser()->block); result = Fast_CallBuilder_build(&builder); Fast_CallBuilder__deinit(&builder); } return result; error: return NULL; }
/* ::cortex::Fast::Element::construct() */ cx_int16 Fast_Element_construct(Fast_Element _this) { /* $begin(::cortex::Fast::Element::construct) */ cx_type lvalueType, rvalueType; Fast_Storage(_this)->kind = Fast_ElementStorage; lvalueType = Fast_Expression_getType(_this->lvalue); if (lvalueType) { if (lvalueType->kind == CX_COLLECTION) { rvalueType = Fast_Expression_getType(_this->rvalue); if (rvalueType) { if (cx_collection(lvalueType)->kind != CX_MAP) { if (!cx_type_castable(cx_type(cx_uint32_o), rvalueType)) { cx_id id; Fast_Parser_error(yparser(), "expected integer expression for index, got '%s'", Fast_Parser_id(rvalueType, id)); goto error; } } else { if (!cx_type_castable(cx_map(lvalueType)->keyType, rvalueType)) { cx_id id, id2; Fast_Parser_error(yparser(), "expected expression of type '%s' for key, got '%s'", Fast_Parser_id(cx_map(lvalueType)->keyType, id), Fast_Parser_id(rvalueType, id2)); goto error; } } } /* Set type of expression */ cx_set(&Fast_Expression(_this)->type, cx_collection(lvalueType)->elementType); } else { cx_id id; Fast_Parser_error(yparser(), "cannot obtain element from _this of non-collection type '%s'", Fast_Parser_id(lvalueType, id)); goto error; } } else { Fast_Parser_error(yparser(), "dynamic expressions are not yet supported"); goto error; } Fast_Expression(_this)->isReference = cx_collection(lvalueType)->elementType->reference; return Fast_Storage_construct(Fast_Storage(_this)); error: return -1; /* $end */ }
/* ::cortex::Fast::Member::construct() */ cx_int16 Fast_Member_construct(Fast_Member _this) { /* $begin(::cortex::Fast::Member::construct) */ Fast_Storage(_this)->kind = Fast_MemberStorage; if (!(_this->lvalue && _this->rvalue)) { goto error; } /* If member-_this can be determined at compile-time, resolve it */ if (_this->lvalue->type) { /* Type must be a known _this at compile-time */ if (Fast_Node(_this->rvalue)->kind == Fast_LiteralExpr) { /* Member-expression must be a literal */ switch(Fast_Literal(_this->rvalue)->kind) { case Fast_Int: /* Resolve the nth member of a type */ Fast_Parser_error(yparser(), "resolving members by index not yet supported"); goto error; break; case Fast_Text: /* Resolve member by name */ /* Validate that string does not exceed 512 characters */ if (strlen(Fast_String(_this->rvalue)->value) >= 512) { Fast_Parser_error(yparser(), "identifiers longer than 511 characters are not supported"); goto error; } if (Fast_Member_resolveMember(_this, _this->lvalue->type, Fast_String(_this->rvalue)->value)) { goto error; } break; default: Fast_Parser_error(yparser(), "invalid member expression"); goto error; break; } } } Fast_Expression(_this)->isReference = Fast_Expression(_this)->type->reference; return Fast_Storage_construct(Fast_Storage(_this)); error: return -1; /* $end */ }
/* ::cortex::Fast::Member::toIc(ic::program program,ic::storage storage,bool stored) */ ic_node Fast_Member_toIc_v(Fast_Member _this, ic_program program, ic_storage storage, cx_bool stored) { /* $begin(::cortex::Fast::Member::toIc) */ ic_member result = NULL; cx_member member; ic_node lvalue; CX_UNUSED(stored); CX_UNUSED(storage); /* Get lvalue & rvalue */ lvalue = Fast_Node_toIc(Fast_Node(_this->lvalue), program, NULL, FALSE); if (Fast_Node(_this->rvalue)->kind == Fast_LiteralExpr) { if (Fast_Literal(_this->rvalue)->kind == Fast_Text) { cx_type t = Fast_Expression_getType(_this->lvalue); if (cx_instanceof(cx_type(cx_interface_o), t)) { cx_interface baseType = cx_interface(t); member = cx_interface_resolveMember(baseType, Fast_String(_this->rvalue)->value); } else { cx_id id; Fast_Parser_error(yparser(), "cannot resolve members on non-interface type '%s'", Fast_Parser_id(t, id)); goto error; } } else { Fast_Parser_error(yparser(), "dynamic resolving of members not yet supported."); goto error; } } else { Fast_Parser_error(yparser(), "dynamic resolving of members not yet supported."); goto error; } if (member) { result = ic_program_getMember(program, ic_storage(lvalue), member); } return (ic_node)result; error: return NULL; /* $end */ }
/* ::cortex::Fast::StaticInitializer::define() */ cx_int16 Fast_StaticInitializer_define(Fast_StaticInitializer _this) { /* $begin(::cortex::Fast::StaticInitializer::define) */ cx_uint32 variable; cx_object o; /* Types are defined during 1st pass. All other objects are defined when a program starts. Defining types * at compile-time is required to do validity checking while parsing. On the other hand, objects cannot be * defined at compile-time because class constructors\destructors are not yet defined at that point. This * would cause object creation\destruction without calling the appropriate constructors\destructors. */ for(variable=0; variable<Fast_Initializer(_this)->variableCount; variable++) { o = (cx_object)Fast_Object(Fast_Initializer(_this)->variables[variable].object)->value; if (cx_instanceof(cx_type(cx_type_o), o) || (cx_checkAttr(o, CX_ATTR_SCOPED) && cx_instanceof(cx_type(cx_type_o), cx_parentof(o)))) { if (cx_define(o)) { cx_id id1, id2; Fast_Parser_error(yparser(), "define of variable '%s' of type '%s' failed", Fast_Parser_id(o, id1), Fast_Parser_id(cx_typeof(o), id2)); goto error; } } else { Fast_Expression refVar = Fast_Expression(Fast_Object__create(o)); refVar->isReference = TRUE; /* Always treat object as reference */ Fast_Define defineStmt = Fast_Define__create(refVar); Fast_Parser_addStatement(yparser(), Fast_Node(defineStmt)); Fast_Parser_collect(yparser(), defineStmt); Fast_Parser_collect(yparser(), refVar); } } Fast_Initializer_define_v(Fast_Initializer(_this)); return 0; error: return -1; /* $end */ }
/* ::cortex::Fast::DelegateCall::construct() */ cx_int16 Fast_DelegateCall_construct(Fast_DelegateCall _this) { /* $begin(::cortex::Fast::DelegateCall::construct) */ if (!_this->expr) { Fast_Parser_error(yparser(), "no expression provided for delegate call"); goto error; } else { cx_uint32 i; cx_delegate type = cx_delegate(Fast_Expression_getType(_this->expr)); /* Create expression to obtain pointer to the instance */ Fast_String instanceString = Fast_String__create("instance"); Fast_Member iExpr = Fast_Member__create(_this->expr, Fast_Expression(instanceString)); cx_set(&Fast_Call(_this)->instanceExpr, iExpr); Fast_Parser_collect(yparser(), iExpr); Fast_Parser_collect(yparser(), instanceString); /* Set function expression to delegate */ cx_set(&Fast_Call(_this)->functionExpr, _this->expr); /* Set parameters */ cx_set(&Fast_Call(_this)->returnType, type->returnType); Fast_Call(_this)->returnsReference = type->returnsReference; cx_parameter_seq__size(&Fast_Call(_this)->parameters, type->parameters.length); for (i = 0; i < type->parameters.length; i++) { cx_set(&Fast_Call(_this)->parameters.buffer[i].type, type->parameters.buffer[i].type); Fast_Call(_this)->parameters.buffer[i].passByReference = type->parameters.buffer[i].passByReference; } } return Fast_Call_construct(Fast_Call(_this)); error: return -1; /* $end */ }
/* ::cortex::Fast::StaticInitializer::construct() */ cx_int16 Fast_StaticInitializer_construct(Fast_StaticInitializer _this) { /* $begin(::cortex::Fast::StaticInitializer::construct) */ cx_int8 variable; /* Copy offsets of variables into frames */ for(variable=0; variable<Fast_Initializer(_this)->variableCount; variable++) { _this->frames[0].ptr[variable] = (cx_word)Fast_Object(Fast_Initializer(_this)->variables[variable].object)->value; if (!_this->frames[0].ptr[variable]) { Fast_Parser_error(yparser(), "non-static variable in static initializer"); goto error; } } return Fast_Initializer_construct(Fast_Initializer(_this)); error: return -1; /* $end */ }
/* Create a call-expression */ Fast_Call Fast_createCall(Fast_Expression instance, cx_string function, cx_uint32 numArgs, ...) { Fast_Expression args = NULL, arg = NULL; va_list arglist; cx_uint32 i; /* Create comma-expression if there is more than one argument */ va_start(arglist, numArgs); if (numArgs > 1) { args = Fast_Expression(Fast_Comma__create()); for(i=0; i<numArgs; i++) { arg = va_arg(arglist, Fast_Expression); Fast_Comma_addExpression(Fast_Comma(args), arg); } } else if (numArgs) { args = va_arg(arglist, Fast_Expression); } va_end(arglist); if (args) { Fast_Parser_collect(yparser(), args); } return Fast_createCallWithArguments(instance, function, args); }
/* ::cortex::Fast::Expression::cast(type type,bool isReference) */ Fast_Expression Fast_Expression_cast(Fast_Expression _this, cx_type type, cx_bool isReference) { /* $begin(::cortex::Fast::Expression::cast) */ cx_type exprType, refType; Fast_Expression result = NULL; cx_bool castRequired = TRUE; cx_assert(type != NULL, "cannot cast to unknown type NULL"); exprType = Fast_Expression_getType(_this); if((_this->deref == Fast_ByReference) && !isReference && !exprType->reference) { refType = cx_object_o; } else { refType = exprType; } /* If types are different, cast */ if (refType != type) { if (!exprType) { /* If expression is an untyped initializer, create an anonymous variable of the destination type * and assign it to the initializer. */ if(Fast_Node(_this)->kind == Fast_InitializerExpr) { Fast_Expression local = Fast_Expression(Fast_Temporary__create(type, FALSE)); Fast_InitializerExpression_insert(Fast_InitializerExpression(_this), local); result = local; castRequired = TRUE; }else { castRequired = FALSE; } } else if (cx_type_castable(type, refType)) { void *value = NULL; /* If expression is a literal or constant create new literal of right type */ value = (void*)Fast_Expression_getValue(_this); if (value) { if (type->reference && (Fast_Node(_this)->kind == Fast_LiteralExpr)) { /* If destination type is a reference and the literal is a string this results * in a resolve at run-time. */ switch(Fast_Literal(_this)->kind) { case Fast_Text: break; case Fast_Nothing: /* No cast required */ break; default: { cx_id id1, id2; /* Invalid cast */ Fast_Parser_error(yparser(), "cannot cast from '%s' to '%s'", Fast_Parser_id(exprType, id1), Fast_Parser_id(type, id2)); break; } } } /* Create literal expressions based on destination type */ switch(cx_primitive(type)->kind) { case CX_BOOLEAN: { cx_bool dstValue = FALSE; cx_convert(cx_primitive(exprType), value, cx_primitive(cx_bool_o), &dstValue); result = Fast_Expression(Fast_Boolean__create(dstValue)); break; } case CX_CHARACTER: { cx_char dstValue; cx_convert(cx_primitive(exprType), value, cx_primitive(cx_char_o), &dstValue); result = Fast_Expression(Fast_Character__create(dstValue)); break; } case CX_BINARY: case CX_UINTEGER: { cx_uint64 dstValue; cx_convert(cx_primitive(exprType), value, cx_primitive(cx_uint64_o), &dstValue); result = Fast_Expression(Fast_Integer__create(dstValue)); break; } case CX_INTEGER: { cx_int64 dstValue; cx_convert(cx_primitive(exprType), value, cx_primitive(cx_int64_o), &dstValue); result = Fast_Expression(Fast_SignedInteger__create(dstValue)); break; } case CX_FLOAT: { cx_float64 dstValue; cx_convert(cx_primitive(exprType), value, cx_primitive(cx_float64_o), &dstValue); result = Fast_Expression(Fast_FloatingPoint__create(dstValue)); break; } case CX_TEXT: { cx_string dstValue; cx_convert(cx_primitive(exprType), value, cx_primitive(cx_string_o), &dstValue); result = Fast_Expression(Fast_String__create(dstValue)); break; } case CX_ENUM: case CX_BITMASK: { cx_int32 dstValue; cx_convert(cx_primitive(exprType), value, cx_primitive(cx_int32_o), &dstValue); result = Fast_Expression(Fast_SignedInteger__create(dstValue)); break; } case CX_ALIAS: { cx_int32 dstValue; cx_convert(cx_primitive(exprType), value, cx_primitive(cx_word_o), &dstValue); result = Fast_Expression(Fast_SignedInteger__create(dstValue)); break; } } if (result){ cx_set_ext(result, &Fast_Expression(result)->type, type, "Set correct type after cast"); } } else { /* TODO: This functionality must be pushed down to the assembler. For all this function is concerned a cast should only be required when a type is a) castable and b) not compatible. */ /* If both types are primitive make sure that no cast is inserted for primitives * of the same kind or 'score' to the same width */ if ((refType->kind == CX_PRIMITIVE) && (type->kind == CX_PRIMITIVE) && (Fast_Expression_getCastScore(cx_primitive(refType)) == Fast_Expression_getCastScore(cx_primitive(type)))) { if (cx_primitive(exprType)->width != cx_primitive(type)->width) { result = Fast_Expression(Fast_Cast__create(type, _this, isReference)); } else { /* Types have the same width, so no cast required */ castRequired = FALSE; } /* Interface-downcasting doesn't require an explicit cast */ } else if (!cx_instanceof(cx_type(cx_interface_o), type)) { result = Fast_Expression(Fast_Cast__create(type, _this, isReference)); } else { castRequired = FALSE; } } /* If object is a reference and targetType is string, insert toString operation */ } else /*if (_this->isReference || Fast_Expression_getType(_this)->reference)*/ { if ((type->kind == CX_PRIMITIVE) && (cx_primitive(type)->kind == CX_TEXT)) { /* Create call-expression */ result = Fast_Expression(Fast_createCallWithArguments(_this, "toString", NULL)); if (!result) { goto error; } cx_keep(result); /* If type is of a generic reference type, accept any reference without cast */ } else if (type->kind == CX_VOID && type->reference) { castRequired = FALSE; /* If assigning to a generic reference, insert cast */ } else if (exprType->kind == CX_VOID && exprType->reference && isReference) { result = Fast_Expression(Fast_Cast__create(type, _this, isReference)); } } } else { castRequired = FALSE; } if (result && castRequired) { Fast_Parser_collect(yparser(), result); } else { if (castRequired) { cx_id id1, id2; Fast_Parser_error(yparser(), "no conversion from '%s' to '%s'", Fast_Parser_id(exprType, id1), Fast_Parser_id(type, id2)); } } return result; error: return NULL; /* $end */ }
/* $end */ corto_int16 _ast_Ternary_construct( ast_Ternary this) { /* $begin(corto/ast/Ternary/construct) */ ast_Node trueBranch=NULL, falseBranch=NULL; ast_Expression trueExpr, falseExpr; corto_type resultType = ast_Expression_getType(this->result); ast_Node(this)->kind = Ast_TernaryExpr; /* Create true statement */ trueBranch = ast_Node(ast_Parser_blockPush(yparser(), FALSE)); trueExpr = ast_Expression(ast_Parser_binaryExpr(yparser(), this->result, this->ifTrue, CORTO_ASSIGN)); ast_Block_addStatement(ast_Block(trueBranch), ast_Node(trueExpr)); ast_Parser_blockPop(yparser()); /* Create false statement */ falseBranch = ast_Node(ast_Parser_blockPush(yparser(), FALSE)); falseExpr = ast_Expression(ast_Parser_binaryExpr(yparser(), this->result, this->ifFalse, CORTO_ASSIGN)); ast_Block_addStatement(ast_Block(falseBranch), ast_Node(falseExpr)); ast_Parser_blockPop(yparser()); /* Store both expressions in this */ corto_setref(&this->ifTrueExpr, trueExpr); corto_setref(&this->ifFalseExpr, falseExpr); /* Create condition */
/* Parse embedded expression */ cx_char *Fast_String_parseEmbedded(Fast_String _this, cx_char *expr) { cx_char ch, *ptr; cx_uint32 nesting; Fast_Expression element; cx_bool bracketExpr = FALSE; if (!maskSet) { cx_tokenMaskSet(alphaMask, ":abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_"); cx_tokenMaskSet(numericMask, "0123456789"); } ptr = expr; if (*ptr == '{') { bracketExpr = TRUE; expr = ++ptr; /* Progress expression as well to skip the initial '{' */ nesting = 1; while((ch = *ptr) && nesting) { switch(ch) { case '{': nesting++; break; case '}': nesting--; break; } ptr++; } ptr--; /* Skip the last '{' */ } else { /* If character is not a '{' parse a variable-name which is * delimited by a non-alphanumeric character. Additionally * variable names cannot start with a number. */ if (!alphaMask[(int)*ptr]) { yparser()->line = Fast_Node(_this)->line; yparser()->column = Fast_Node(_this)->column; Fast_Parser_error(yparser(), "invalid embedded expression at '%s'", expr); goto error; } ptr++; while((ch = *ptr) && (alphaMask[(int)ch] || numericMask[(int)ch])) { if (ch == ':') { ptr++; if (*ptr != ':') { ptr--; break; } } ptr++; } } ch = *ptr; *ptr = '\0'; element = Fast_Parser_parseExpression(yparser(), expr, _this->block, _this->scope, Fast_Node(_this)->line, Fast_Node(_this)->column); if (element) { cx_llAppend(_this->elements, element); cx_keep(element); } else { goto error; } *ptr = ch; if (bracketExpr) { ptr++; } return ptr; error: return NULL; }
/* ::cortex::Fast::String::toIc(ic::program program,ic::storage storage,bool stored) */ ic_node Fast_String_toIc_v(Fast_String _this, ic_program program, ic_storage storage, cx_bool stored) { /* $begin(::cortex::Fast::String::toIc) */ ic_node result = NULL; CX_UNUSED(storage); CX_UNUSED(stored); /* Parse string after parsing script and thus not interfere with parser */ if (Fast_String_parse(_this)) { goto error; } if (!cx_llSize(_this->elements)) { result = (ic_node)ic_literal__create((cx_any){cx_type(cx_string_o), &_this->value, FALSE}); } else { if (stored) { cx_iter elementIter; Fast_Expression element; ic_node icElement1, icElement2; cx_uint32 elementCount = cx_llSize(_this->elements); cx_bool stored = FALSE; ic_node dummy; cx_uint32 accPushCount = 0; cx_type elementType; if (storage && (storage->type != cx_type(cx_string_o))) { Fast_Parser_error(yparser(), "storage for string-expression '%s' has invalid type (%s)", _this->value, cx_nameof(storage->type)); goto error; } dummy = (ic_node)ic_literal__create((cx_any){cx_type(cx_string_o), NULL, FALSE}); result = (ic_node)storage; elementIter = cx_llIter(_this->elements); while(cx_iterHasNext(&elementIter)) { ic_accumulator acc = ic_program_pushAccumulator(program, (cx_type)cx_string_o, FALSE, FALSE); accPushCount++; element = cx_iterNext(&elementIter); elementType = Fast_Expression_getType(element); if (!elementType) { element = Fast_Expression(Fast_String__create(CX_NULL_STRING)); } else if (elementType != cx_type(cx_string_o)) { element = Fast_Expression_cast(element, cx_type(cx_string_o), FALSE); if(!element) { goto error; } } icElement1 = Fast_Node_toIc(Fast_Node(element), program, (ic_storage)acc, TRUE); if (!icElement1) { goto error; } if (elementCount == 1) { if (storage) { IC_2(program, Fast_Node(_this)->line, ic_strcpy, storage, icElement1, IC_DEREF_VALUE, IC_DEREF_VALUE); } else { result = (ic_node)icElement1; } stored = TRUE; } else { if (elementCount) { if (cx_iterHasNext(&elementIter)) { ic_accumulator acc = ic_program_pushAccumulator(program, (cx_type)cx_string_o, FALSE, FALSE); accPushCount++; element = cx_iterNext(&elementIter); elementType = Fast_Expression_getType(element); if (!elementType) { element = Fast_Expression(Fast_String__create(CX_NULL_STRING)); } else if (elementType && (Fast_Expression_getType(element) != cx_type(cx_string_o))) { element = Fast_Expression_cast(element, cx_type(cx_string_o), FALSE); if (!element) { goto error; } } icElement2 = Fast_Node_toIc(Fast_Node(element), program, (ic_storage)acc, TRUE); if (!icElement2) { goto error; } IC_2(program, Fast_Node(_this)->line, ic_strcat, icElement1, icElement2, IC_DEREF_VALUE, IC_DEREF_VALUE); elementCount--; } } else { IC_2(program, Fast_Node(_this)->line, ic_strcat, icElement1, dummy, IC_DEREF_VALUE, IC_DEREF_VALUE); } } elementCount--; } /* If string is not yet copied, insert copy instruction */ if (!stored) { IC_2(program, Fast_Node(_this)->line, ic_strcpy, storage, dummy, IC_DEREF_VALUE, IC_DEREF_VALUE); stored = TRUE; } while(accPushCount) { ic_program_popAccumulator(program); accPushCount--; } } } return result; error: return NULL; /* $end */ }
* Only code written between the begin and end tags will be preserved * when the file is regenerated. */ #include <corto/ast/ast.h> /* $header() */ #include "ast__private.h" /* $end */ corto_int16 _ast_DelegateCall_construct( ast_DelegateCall this) { /* $begin(corto/ast/DelegateCall/construct) */ if (!this->expr) { ast_Parser_error(yparser(), "no expression provided for delegate call"); goto error; } else { corto_uint32 i; corto_delegate type = corto_delegate(ast_Expression_getType(this->expr)); /* Create expression to obtain pointer to the instance */ ast_String instanceString = ast_StringCreate("instance"); ast_Member iExpr = ast_MemberCreate(this->expr, ast_Expression(instanceString)); corto_setref(&ast_Call(this)->instanceExpr, iExpr); ast_Parser_collect(yparser(), iExpr); ast_Parser_collect(yparser(), instanceString); /* Set function expression to delegate */ corto_setref(&ast_Call(this)->functionExpr, this->expr);
cx_word Fast_Initializer_offset(Fast_StaticInitializer _this, cx_uint32 variable) { cx_word result, base; cx_uint16 fp = Fast_Initializer(_this)->fp; Fast_InitializerFrame *frame = &Fast_Initializer(_this)->frames[fp?fp-1:0]; Fast_StaticInitializerFrame *baseFrame = &(_this->frames[fp?fp-1:0]); Fast_InitializerFrame *thisFrame = &Fast_Initializer(_this)->frames[fp]; result = 0; base = baseFrame->ptr[variable]; if (!base) { Fast_Parser_error(yparser(), "parser error: base is zero in offset calculation"); goto error; } /* Switch on current type */ switch(frame->type->kind) { case CX_PRIMITIVE: result = base; break; case CX_COMPOSITE: if (fp) { result = base + thisFrame->member->offset; } else { result = base; } break; case CX_ITERATOR: result = base; break; case CX_COLLECTION: { if (fp) { cx_uint32 elementSize = cx_type_sizeof(cx_collection(frame->type)->elementType); switch(cx_collection(frame->type)->kind) { case CX_SEQUENCE: ((cx_objectSeq*)base)->length++; ((cx_objectSeq*)base)->buffer = cx_realloc(((cx_objectSeq*)base)->buffer, ((cx_objectSeq*)base)->length * elementSize); base = (cx_word)((cx_objectSeq*)base)->buffer; case CX_ARRAY: result = base + thisFrame->location * cx_type_sizeof(cx_collection(frame->type)->elementType); memset((void*)result, 0, elementSize); break; case CX_LIST: { if (cx_collection_elementRequiresAlloc(cx_collection(frame->type))) { result = (cx_word)cx_calloc(elementSize); } if (!*(cx_ll*)base) { *(cx_ll*)base = cx_llNew(); } cx_llAppend(*(cx_ll*)base, (void*)result); if (!result) { result = (cx_word)cx_llGetPtr(*(cx_ll*)base, cx_llSize(*(cx_ll*)base)-1); } break; } case CX_MAP: { cx_type keyType = cx_map(frame->type)->keyType; if (!thisFrame->isKey) { if (cx_collection_elementRequiresAlloc(cx_collection(frame->type))) { result = (cx_word)cx_calloc(elementSize); } if (!*(cx_rbtree*)base) { *(cx_rbtree*)base = cx_rbtreeNew(frame->type); } cx_rbtreeSet(*(cx_rbtree*)base, (void*)_this->frames[fp].keyPtr[variable], (void*)result); if (!result) { if (_this->frames[fp].keyPtr[variable]) { result = (cx_word)cx_rbtreeGetPtr(*(cx_rbtree*)base, (void*)_this->frames[fp].keyPtr[variable]); } else { Fast_Parser_error(yparser(), "cannot set element without keyvalue"); goto error; } } } else { result = (cx_word)cx_calloc(cx_type_sizeof(keyType)); _this->frames[fp].keyPtr[variable] = result; thisFrame->isKey = FALSE; } break; } } } else { result = base; } break; } default: { cx_id id; Fast_Parser_error(yparser(), "invalid initializer type '%s'", Fast_Parser_id(frame->type, id)); break; } } return result; error: return 0; }