Type* copyType(Type* t) { if(t == NULL) return NULL; Type* copy = malloc(sizeof(Type)); copy->type = t->type; copy->optional = t->optional; if(t->type == TYPE_LAMBDA) { copy->typedata.lambda.arguments = copyTypeArray(t->typedata.lambda.arguments); copy->typedata.lambda.returntype = copyType(t->typedata.lambda.returntype); copy->typedata.lambda.body = t->typedata.lambda.body; } else if(t->type == TYPE_CLASS) { copy->typedata._class.classname = t->typedata._class.classname == NULL ? NULL : strdup(t->typedata._class.classname); copy->typedata._class.shadow = t->typedata._class.shadow; // number of $s copy->typedata._class.parameters = copyTypeArray(t->typedata._class.parameters); // Xxx{T from Yyy} } else if(t->type == TYPE_PARAMETERIZED) { copy->typedata.parameterized.label = t->typedata.parameterized.label == NULL ? NULL : strdup(t->typedata.parameterized.label); copy->typedata.parameterized.shadow = t->typedata.parameterized.shadow; // number of $s copy->typedata.parameterized.lowerbound = copyType(t->typedata.parameterized.lowerbound); copy->typedata.parameterized.upperbound = copyType(t->typedata.parameterized.upperbound); } copy->arrayed = t->arrayed; copy->alias = t->alias == NULL ? NULL : strdup(t->alias); copy->specialty = t->specialty == NULL ? NULL : strdup(t->specialty); return copy; }
boost::optional<SemanticError*> PropertySymbolTable::addMethod(Type* returntype, vector<pair<string, TypeArray*> >* segments_arguments, int flags) { string name = getSymbolNameOf(segments_arguments); if(properties.count(name)) { string temp = "duplicate method signature is " + name; return boost::optional<SemanticError*>(new SemanticError(MULTIPLE_METHOD_DEFINITION, temp)); } if(flags & PROPERTY_ABSTRACT) { abstract = true; } Type* method = MakeType(TYPE_LAMBDA); method->typedata.lambda.returntype = copyType(returntype); TypeArray* conglomerate = MakeTypeArray(); for(vector<pair<string, TypeArray*> >::iterator it = segments_arguments->begin(); it != segments_arguments->end(); ++it) { int i; for(i = 0; i < it->second->typecount; i++) AddTypeToTypeArray(copyType(it->second->types[i]), conglomerate); } method->typedata.lambda.arguments = conglomerate; ObjectProperty* prop = new ObjectProperty; prop->flags = flags; prop->type = method; prop->casing = getCasingNameOf(segments_arguments); prop->address = name; properties[name] = prop; return boost::optional<SemanticError*>(); }
ReadOnlyPropertySymbolTable* PropertySymbolTable::resolveParameters(vector<Type*>& parameters) { TypeParameterizer parameterizer; map<string, ObjectProperty*>* newprops = new map<string, ObjectProperty*>(); for(map<string, ObjectProperty*>::iterator it = properties.begin(); it != properties.end(); ++it) { string casing, oldcasing = it->second->casing; ObjectProperty* newprop = new ObjectProperty(); newprop->type = copyType(it->second->type); newprop->flags = it->second->flags; newprop->address = it->second->address; parameterizer.applyParameterizations(&newprop->type, getParameters(), parameters); int i = 0, c = 0; while(c < oldcasing.length()) { if(oldcasing.at(c) == '#') { casing += analyzer->getNameForType(newprop->type->typedata.lambda.arguments->types[i]); i++; } else { casing += oldcasing.at(c); } c++; } newprop->casing = casing; (*newprops)[casing] = newprop; } vector<Type*>* newneeds = new vector<Type*>(); for(vector<Type*>::iterator it = needs->begin(); it != needs->end(); ++it) { Type* newneed = copyType(*it); parameterizer.applyParameterizations(&newneed, getParameters(), parameters); newneeds->push_back(newneed); } return new DerivedPropertySymbolTable(*analyzer, *newneeds, *newprops, parentage); return this; }
void propagateInheritanceTables(PropertySymbolTable* child, PropertySymbolTable* parent, bool extend) { for(map<string, ObjectProperty*>::iterator it = parent->properties.begin(); it != parent->properties.end(); ++it) { if(!extend && !(it->second->flags & PROPERTY_PUBLIC)) continue; map<string, ObjectProperty*>::iterator searcher = child->properties.find(it->first); if(searcher == child->properties.end()) { ObjectProperty* propagate = new ObjectProperty; propagate->type = copyType(it->second->type); propagate->flags = it->second->flags; propagate->casing = it->second->casing; propagate->address = it->second->address; if(!extend) { propagate->flags |= PROPERTY_ABSTRACT; child->abstract = true; } else if(propagate->flags & PROPERTY_ABSTRACT) { child->abstract = true; } child->properties[it->first] = propagate; if(extend && propagate->flags & PROPERTY_NEED) { child->analyzer->assertNeedIsNotCircular(child->classname, propagate->type); child->getNeeds()->push_back(propagate->type); } } else { searcher->second->address = it->second->address; } } }
TypeArray* copyTypeArray(TypeArray* ta) { if(ta == NULL) return NULL; TypeArray* copy = malloc(sizeof(TypeArray)); copy->typecount = ta->typecount; copy->types = malloc(copy->typecount * sizeof(Type*)); int i; for(i = 0; i < ta->typecount; i++) { copy->types[i] = copyType(ta->types[i]); } return copy; }
bool TypeAnalyzer::isAutoboxedType(Type* type, Type** boxed) { if(type->type == TYPE_MATCHALL) return false; // shouldn't be here...throw exception? if(type->type == TYPE_UNUSABLE) return false; // need to return a List<T> if(type->arrayed) { *boxed = MakeType(TYPE_CLASS); Type* loweredtype = copyType(type); loweredtype->arrayed--; (*boxed)->typedata._class.classname = strdup("List"); (*boxed)->typedata._class.parameters = MakeTypeArray(); AddTypeToTypeArray(loweredtype, (*boxed)->typedata._class.parameters); return true; } // need to return a generic autoboxed type according to arguments/return if(type->type == TYPE_LAMBDA) { *boxed = MakeType(TYPE_CLASS); (*boxed)->typedata._class.classname = strdup("lambda"); return true; } // shouldn't ever get here,..unless I decide to make, say, T?.exists() and/or T?.applyIfExists(fn(T)) if(type->optional) return false; if(isPrimitiveTypeBool(type)) { *boxed = MakeType(TYPE_CLASS); (*boxed)->typedata._class.classname = strdup("Bool"); return true; } if(isPrimitiveTypeText(type)) { *boxed = MakeType(TYPE_CLASS); (*boxed)->typedata._class.classname = strdup("Text"); return true; } if(isPrimitiveTypeNum(type)) { *boxed = MakeType(TYPE_CLASS); (*boxed)->typedata._class.classname = strdup("Num"); return true; } return false; }
void propagateInheritanceTables(PropertySymbolTable* child, PropertySymbolTable* parent, bool extend, ErrorTracker& errors) { for(map<string, ObjectProperty*>::iterator it = parent->properties.begin(); it != parent->properties.end(); ++it) { if(!extend && !(it->second->flags & PROPERTY_PUBLIC)) continue; map<string, ObjectProperty*>::iterator searcher = child->properties.find(it->first); if(searcher == child->properties.end()) { ObjectProperty* propagate = new ObjectProperty; propagate->type = copyType(it->second->type); propagate->flags = it->second->flags; propagate->casing = it->second->casing; propagate->address = it->second->address; if(!extend) { propagate->flags |= PROPERTY_ABSTRACT; child->abstract = true; } else if(propagate->flags & PROPERTY_ABSTRACT) { child->abstract = true; } child->properties[it->first] = propagate; if(extend && propagate->flags & PROPERTY_NEED) { child->analyzer->assertNeedIsNotCircular(child->classname, propagate->type); child->getNeeds()->push_back(propagate->type); } } else { searcher->second->address = it->second->address; if(searcher->second->type->type == TYPE_LAMBDA) if(it->second->type->typedata.lambda.returntype != NULL) if(searcher->second->type->typedata.lambda.returntype == NULL || !child->analyzer->isASubtypeOfB( searcher->second->type->typedata.lambda.returntype, // this is contravariance it->second->type->typedata.lambda.returntype // Check parent return is a subtype of child return ) ) { errors.addError(new SemanticError(INVALID_CHILD_RETURN_TYPE, "method " + searcher->second->address + " on class " + child->classname, NULL, "")); } } } }
boost::optional<SemanticError*> PropertySymbolTable::addProvision(Type* provided, int flags) { string name = analyzer->getNameForType(provided) + "<-"; if(provided->specialty != NULL) name += provided->specialty; if(properties.count(name)) { string temp = "duplicate provisoning is " + name; return boost::optional<SemanticError*>(new SemanticError(DUPLICATE_PROPERTY_DEFINITION, temp)); } Type* method = MakeType(TYPE_LAMBDA); method->typedata.lambda.returntype = copyType(provided); method->typedata.lambda.arguments = MakeTypeArray(); //TODO injections with curried ctors or arguments! ObjectProperty* prop = new ObjectProperty; prop->type = method; prop->casing = name; prop->address = name; prop->flags = flags; properties[name] = prop; return boost::optional<SemanticError*>(); }