public FixedVariableDecl(string name, Expression value, TokenPosition position) : base(position) { SetName(name); this.value = value; this.variable = null; }
public FunctionArgument(Expression typeExpression, bool @params, string name, TokenPosition position) : base(position) { SetName(name); this.typeExpression = typeExpression; this.@params = @params; this.variable = null; }
public PropertyAccessor(MemberFlags flags, AstNode children, TokenPosition position) : base(null, children, position) { this.flags = flags; this.property = null; this.selfLocal = null; this.indices = null; this.indexerVariables = null; }
public CatchStatement(Expression exceptionType, string name, AstNode children, TokenPosition position) : base(children, position) { SetName(name); this.exceptionType = exceptionType; this.context = null; this.variable = null; }
public EventAccessorDefinition(MemberFlags flags, string name, AstNode children, TokenPosition position) : base(children, position) { SetName(name); this.flags = flags; this.eventVariable = null; this.function = null; this.selfLocal = null; this.valueLocal = null; }
protected Function(ChelaModule module) : base(module) { this.name = string.Empty; this.flags = MemberFlags.Default; this.parentScope = null; this.basicBlocks = new List<BasicBlock> (); this.lexicalScopes = new List<LexicalScope>(); this.locals = new List<LocalVariable> (); this.position = null; this.exceptionContext = null; this.returnBlock = null; this.returningVar = null; this.returnValueVar = null; this.genericPrototype = GenericPrototype.Empty; this.arguments = null; }
private void DefineGeneratorBody(FunctionDefinition node) { // Get entry function. Function entryFunction = node.GetFunction(); // Rebase his locals. entryFunction.RebaseLocals(); // Create the generator class. Scope spaceScope = entryFunction.GetParentScope(); Class generatorClass = new Class(GenSym(), MemberFlags.Internal, spaceScope); node.GeneratorClass = generatorClass; // Use the same generic prototype as the entry point function. generatorClass.SetGenericPrototype(entryFunction.GetGenericPrototype()); // Add the generator class to the same scope as the function. if(spaceScope.IsClass() || spaceScope.IsStructure()) { Structure parentClass = (Structure)spaceScope; parentClass.AddType(generatorClass); } else if(spaceScope.IsNamespace()) { Namespace parentSpace = (Namespace)spaceScope; parentSpace.AddMember(generatorClass); } else { Error(node, "Cannot create generator class in {0}", spaceScope.GetFullName()); } // Add the enumerable interface. Structure enumerableIface = null; if(node.IsEnumerable) { enumerableIface = currentModule.GetEnumerableIface(); if(node.IsGenericIterator) { enumerableIface = currentModule.GetEnumerableGIface(); GenericInstance gargs = new GenericInstance(enumerableIface.GetGenericPrototype(), new IChelaType[]{node.YieldType}); enumerableIface = (Structure)enumerableIface.InstanceGeneric(gargs, currentModule); } generatorClass.AddInterface(enumerableIface); } // Add the enumerator interface. Structure enumeratorIface = currentModule.GetEnumeratorIface(); if(node.IsGenericIterator) { enumeratorIface = currentModule.GetEnumeratorGIface(); GenericInstance gargs = new GenericInstance(enumeratorIface.GetGenericPrototype(), new IChelaType[]{node.YieldType}); enumeratorIface = (Structure)enumeratorIface.InstanceGeneric(gargs, currentModule); } generatorClass.AddInterface(enumeratorIface); // Create the yielded field. FieldVariable yieldedValue = new FieldVariable("yielded", MemberFlags.Private, node.YieldType, generatorClass); generatorClass.AddField(yieldedValue); node.YieldedValue = yieldedValue; // Create the generator state variable. FieldVariable generatorState = new FieldVariable("state", MemberFlags.Private, ChelaType.GetIntType(), generatorClass); generatorClass.AddField(generatorState); node.GeneratorState = generatorState; // Encapsulate the locals in fields. foreach(LocalVariable local in entryFunction.GetLocals()) { if(!local.IsPseudoLocal) continue; // Variables containing arguments must be public. MemberFlags access = MemberFlags.Private; if(local.ArgumentIndex >= 0) access = MemberFlags.Public; // Create the field to hold the state. FieldVariable localField = new FieldVariable(GenSym(), access, local.GetVariableType(), generatorClass); generatorClass.AddField(localField); local.ActualVariable = localField; } // Create an instance of the generator class. Structure generatorClassInstance = generatorClass.GetClassInstance(); if(generatorClass.GetGenericPrototype().GetPlaceHolderCount() != 0) { // Create an instance using the same placeholders. GenericPrototype proto = generatorClass.GetGenericPrototype(); int numargs = proto.GetPlaceHolderCount(); IChelaType[] protoInstance = new IChelaType[numargs]; for(int i = 0; i < numargs; ++i) protoInstance[i] = proto.GetPlaceHolder(i); // Instance the generic class. GenericInstance instance = new GenericInstance(proto, protoInstance); generatorClassInstance = (Structure)generatorClassInstance.InstanceGeneric(instance, currentModule); } node.GeneratorClassInstance = generatorClassInstance; // Create the trivial constructor. Function ctor = CreateTrivialConstructor(generatorClass, generatorClassInstance); if(generatorClass.IsGeneric()) ctor = FindFirstConstructor(generatorClassInstance); // Create a local to hold the created closure. LexicalScope topScope = (LexicalScope)node.GetScope(); LocalVariable closureLocal = new LocalVariable("closure", topScope, ReferenceType.Create(generatorClassInstance)); // Create the entry point content. BasicBlock entryBlock = CreateBasicBlock(); entryBlock.SetName("entry"); builder.SetBlock(entryBlock); // Create the closure and store it in his local. builder.CreateNewObject(generatorClassInstance, ctor, 0); builder.CreateStoreLocal(closureLocal); // Load the closure. builder.CreateLoadLocal(closureLocal); // Store the arguments into the closure. FunctionPrototype prototype = node.GetPrototype(); AstNode argument = prototype.GetArguments(); byte index = 0; while(argument != null) { FunctionArgument argNode = (FunctionArgument) argument; // TODO: Forbid ref, out, stream arguments here. // Store the argument in the closure. LocalVariable argVar = argNode.GetVariable(); if(argVar != null) { // Load the closure builder.CreateDup1(); // Load the argument. builder.CreateLoadArg(index); // Store it into the field. builder.CreateStoreField((FieldVariable)argVar.ActualVariable); } // Process the next argument. argument = argument.GetNext(); index++; } // Encapsulate the argument variables. foreach(ArgumentVariable argVar in node.ArgumentVariables) { if(!argVar.IsPseudoArgument) continue; // Create the argument field. FieldVariable argField = new FieldVariable(GenSym(), MemberFlags.Public, argVar.GetVariableType(), generatorClass); generatorClass.AddField(argField); argVar.ActualVariable = argField; // Store the self field. if(!currentFunction.IsStatic() && argVar.GetArgumentIndex() == 0) node.GeneratorSelf = argField; // Load the closure. builder.CreateDup1(); // Load the argument. builder.CreateLoadArg((byte)argVar.GetArgumentIndex()); // Store it into the closure. builder.CreateStoreField(argField); } // Return the generator. builder.CreateRet(); // Notify the yields about their states. int stateIndex = 2; foreach(ReturnStatement yieldStmtn in node.Yields) { yieldStmtn.YieldState = stateIndex; stateIndex += 2; } // Implement IEnumerator. if(node.IsEnumerable) { // Create the object GetEnumerator method. CreateGenerator_GetEnumerator(node, currentModule.GetEnumeratorIface(), false); // Create the generic GetEnumerator method if(node.IsGenericIterator) CreateGenerator_GetEnumerator(node, enumeratorIface, true); } // Create the Current property. CreateGenerator_Current(node, false); if(node.IsGenericIterator) CreateGenerator_Current(node, true); // Create the Reset method. CreateGenerator_Reset(node); // Create the MoveNext method. Function moveNext = CreateGenerator_MoveNext(node); // Create the Dispose method. CreateGenerator_Dispose(node, moveNext); // Fix the inheritance. generatorClass.FixInheritance(); }
public void CreateLoadLocalRef(LocalVariable local) { CreateLoadLocalRef((ushort)local.GetLocalIndex()); }
public override AstNode Visit(CatchStatement node) { // Get the type expression. Expression typeExpression = node.GetExceptionType(); // Visit the type node. typeExpression.Accept(this); // Get the type of the type expression. IChelaType type = typeExpression.GetNodeType(); IChelaType objectType = ExtractActualType(typeExpression, type); // Only accept classes. if(!objectType.IsClass()) Error(node, "only class instances can be exceptions."); // Set the node type. node.SetNodeType(objectType); // Create the catch lexical scope. LexicalScope scope = CreateLexicalScope(node); node.SetScope(scope); // Create the exception variable. string exceptName = node.GetName(); if(exceptName != null && exceptName != "") { LocalVariable exceptLocal = new LocalVariable(exceptName, scope, ReferenceType.Create(objectType)); node.SetVariable(exceptLocal); } // Enter into the catch scope. PushScope(scope); // Visit the children. node.GetChildren().Accept(this); // Restore the scope. PopScope(); return node; }
internal int AddLocal(LocalVariable local) { // TODO: Throw an exception for duplicated variables. members.Add(local.GetName(), local); // Notify the parent function. return parentFunction.AddLocal(local); }
public override AstNode Visit(VariableDeclaration node) { // Get the variable name. string varName = node.GetName(); // Avoid redefinition. if(currentContainer.FindMember(varName) != null) Error(node, "attempting to redefine a variable in a same scope."); // Get the initial value. Expression initialValue = node.GetInitialValue(); // Visit the initial value. // Do this here to use the state previous to the variable declaration. if(initialValue != null) initialValue.Accept(this); // Create the variable. LocalVariable local = new LocalVariable(node.GetName(), (LexicalScope)currentContainer, node.GetNodeType()); // Store it in the node. node.SetVariable(local); // Check the compatibility with the initial value. if(initialValue == null) return node; // Get the variable type and the initial value type. IChelaType varType = node.GetNodeType(); IChelaType valueType = initialValue.GetNodeType(); // Class instances are held by reference. if(varType != valueType && Coerce(node, varType, valueType, initialValue.GetNodeValue()) != varType) Error(node, "cannot implicitly cast from {0} to {1}.", valueType.GetFullName(), varType.GetFullName()); return node; }
public void SetValueLocal(LocalVariable local) { valueLocal = local; }
public override AstNode Visit(FunctionDefinition node) { // Process attributes. ProcessAttributes(node); // Get the prototype. FunctionPrototype prototype = node.GetPrototype(); // Get the function. Function function = prototype.GetFunction(); // Store the definition node in the function. if(function.DefinitionNode != null) Error(node, "multiples definition of a function."); function.DefinitionNode = node; // Check for declarations, interfaces. MemberFlags instanceFlags = function.GetFlags() & MemberFlags.InstanceMask; if(instanceFlags == MemberFlags.Abstract || instanceFlags == MemberFlags.Contract || function.IsExternal()) { if(node.GetChildren() != null) Error(node, "abstract/extern functions cannot have a definition body."); return node; } else { if(node.GetChildren() == null) Error(node, "functions must have a definition."); } // Store the old function. // TODO: Add closures Function oldFunction = currentFunction; currentFunction = function; // Create the function lexical scope. LexicalScope topScope = CreateLexicalScope(node); node.SetScope(topScope); // Use the prototype scope. Scope protoScope = prototype.GetScope(); if(protoScope != null) PushScope(protoScope); // Update the scope. PushScope(topScope); // Push the security. if(function.IsUnsafe()) PushUnsafe(); // Declare the argument variables. AstNode argument = prototype.GetArguments(); int index = 0; while(argument != null) { // Cast the argument node. FunctionArgument argNode = (FunctionArgument)argument; // Set the argument name. string name = argument.GetName(); ArgumentData argData = function.GetArguments()[index++]; argData.Name = name; // Create the argument variable. if(name != null && name != "" && name != "this") { // Create the argument local variable LocalVariable argLocal = new LocalVariable(name, topScope, argNode.GetNodeType()); argLocal.Type = LocalType.Argument; argLocal.ArgumentIndex = index; // Store it in the argument node. argNode.SetVariable(argLocal); } else if(name == "this") { // Create the this argument. node.ArgumentVariables.Add( new ArgumentVariable(0, "this", topScope, argument.GetNodeType()) ); } argument = argument.GetNext(); } // Check the constructor initializer. if(function.IsConstructor()) CheckConstructorInit(node); // Visit his children. VisitList(node.GetChildren()); // Restore the security. if(function.IsUnsafe()) PopUnsafe(); // Restore the scope. PopScope(); // Restore the prototype scope. if(protoScope != null) PopScope(); // Restore the current function. currentFunction = oldFunction; return node; }
public override AstNode Visit(EventAccessorDefinition node) { EventVariable eventVariable = node.GetEvent(); // Build the event flags. MemberFlags flags = node.GetFlags(); if(flags == MemberFlags.ImplicitVis) { flags = eventVariable.GetFlags(); } else { // TODO: Check compatibility. flags |= eventVariable.GetFlags() & ~MemberFlags.VisibilityMask; } // Get the instance type. MemberFlags instanceFlags = MemberFlags.InstanceMask & flags; // Abstract properties cannot have a body. if((instanceFlags == MemberFlags.Abstract || instanceFlags == MemberFlags.Contract) && node.GetChildren() != null) Error(node, "abstract events cannot have a definition body."); // Create the argument list. List<IChelaType> arguments = new List<IChelaType> (); // Add the this argument. IChelaType selfType = null; if(currentContainer.IsStructure() || currentContainer.IsClass() || currentContainer.IsInterface()) { Structure building = (Structure) currentContainer; if(instanceFlags != MemberFlags.Static) { // Instance the building. building = building.GetSelfInstance(); // Create the self argument. selfType = ReferenceType.Create(building); arguments.Add(selfType); } } // Add the value argument. arguments.Add(eventVariable.GetVariableType()); // Create the function type. FunctionType functionType = FunctionType.Create(ChelaType.GetVoidType(), arguments, false); // Build the function name. string functionName = node.GetName() + "_" + eventVariable.GetName(); // Create the function. Function accessor; if(selfType != null) accessor = new Method(functionName, flags, currentContainer); else accessor = new Function(functionName, flags, currentContainer); // Set the arguments. accessor.SetFunctionType(functionType); // Set the function position. accessor.Position = node.GetPosition(); // Store the function in the event. if(node.GetName() == "add") eventVariable.AddModifier = accessor; else eventVariable.RemoveModifier = accessor; // Store the function in his scope. if(currentContainer.IsStructure() || currentContainer.IsClass() || currentContainer.IsInterface()) { Structure building = (Structure)currentContainer; building.AddFunction(functionName, accessor); } else if(currentContainer.IsNamespace()) { Namespace space = (Namespace)currentContainer; space.AddMember(accessor); } else { Error(node, "an event cannot be declared here."); } // If there's a body, declare the "argument" variables. if(node.GetChildren() != null) { LexicalScope scope = CreateLexicalScope(node, accessor); // Add the "this" local. if(selfType != null) new ArgumentVariable(0, "this", scope, selfType); // Add the "value" local LocalVariable valueVar = new LocalVariable("value", scope, eventVariable.GetVariableType()); node.SetValueLocal(valueVar); // Store the scope node.SetScope(scope); } // Set the node function to the accessor. node.SetFunction(accessor); return node; }
internal int AddLocal(LocalVariable local) { // Don't write pseudo locals. if(local.IsPseudoLocal) return -1; // Add the local. this.locals.Add(local); return nextLocalId++; }
public void CreateLoadLocalAddr(LocalVariable local) { if(local.IsPseudoLocal) throw new ModuleException("Cannot use pseudo variable directly."); CreateLoadLocalAddr((ushort)local.GetLocalIndex()); }
public override AstNode Visit(SetAccessorDefinition node) { PropertyVariable property = node.GetProperty(); if(node.GetChildren() == null && property.SetAccessor != null) return node; if(node.GetChildren() != null && property.SetAccessor != null) Error(node, "multiples definitions of the set accessor."); // Build the property flags. MemberFlags flags = node.GetFlags(); if(flags == MemberFlags.ImplicitVis) { flags = property.GetFlags(); } else { // TODO: Check compatibility. flags |= property.GetFlags() & ~MemberFlags.VisibilityMask; } // Get the instance type. MemberFlags instanceFlags = MemberFlags.InstanceMask & flags; // Abstract properties cannot have a body. if((instanceFlags == MemberFlags.Abstract || instanceFlags == MemberFlags.Contract) && node.GetChildren() != null) Error(node, "abstract properties cannot have a definition body."); // Create the set accesor. if(property.SetAccessor == null) { // Create the argument list. List<IChelaType> arguments = new List<IChelaType> (); // Add the this argument. IChelaType selfType = null; if(currentContainer.IsStructure() || currentContainer.IsClass() || currentContainer.IsInterface()) { Structure building = (Structure) currentContainer; if(instanceFlags != MemberFlags.Static) { // Instance the building. building = building.GetSelfInstance(); // Create the self parameter. selfType = ReferenceType.Create(building); arguments.Add(selfType); } } // Append the indices. foreach(IChelaType indexType in property.Indices) arguments.Add(indexType); // Add the value argument. arguments.Add(property.GetVariableType()); // Create the function type. FunctionType functionType = FunctionType.Create(ChelaType.GetVoidType(), arguments, false); // Create the function. Function accessor; if(selfType != null) accessor = new Method("set_" + property.GetName(), flags, currentContainer); else accessor = new Function("set_" + property.GetName(), flags, currentContainer); // Set the arguments. accessor.SetFunctionType(functionType); // Set the function position. accessor.Position = node.GetPosition(); // Store the function in the property. property.SetAccessor = accessor; // Store the function in his scope. if(currentContainer.IsStructure() || currentContainer.IsClass() || currentContainer.IsInterface()) { Structure building = (Structure)currentContainer; building.AddFunction("set_" + property.GetName(), accessor); } else if(currentContainer.IsNamespace()) { Namespace space = (Namespace)currentContainer; space.AddMember(accessor); } else { Error(node, "a property cannot be declared here."); } // If there's a body, declare the "argument" variables. if(node.GetChildren() != null) { LexicalScope scope = CreateLexicalScope(node, accessor); // Add the "this" local. if(selfType != null) new ArgumentVariable(0, "this", scope, selfType); // Add the "value" local LocalVariable valueVar = new LocalVariable("value", scope, property.GetVariableType()); node.SetValueLocal(valueVar); // Add the indices variables. AstNode index = node.GetIndices(); List<LocalVariable> indexerVars = new List<LocalVariable> (); while(index != null) { // Create the local LocalVariable local = new LocalVariable(index.GetName(), scope, index.GetNodeType()); indexerVars.Add(local); // Process the next. index = index.GetNext(); } node.SetIndexerVariables(indexerVars); node.SetScope(scope); } } else { // Check for declaration compatibility. if(flags != property.SetAccessor.GetFlags()) Error(node, "incompatible set accessor declarations."); } // Set the node function to the accessor. node.SetFunction(property.SetAccessor); return node; }
public void CreateStoreLocal(LocalVariable variable) { if(variable.IsPseudoLocal) throw new ModuleException("Cannot use pseudo variable directly."); uint index = (uint)variable.GetLocalIndex(); if(index < 256) CreateStoreLocal((byte)index); else CreateStoreLocalS((ushort)index); }
public void SetVariable(LocalVariable variable) { this.variable = variable; }
public SetAccessorDefinition(MemberFlags flags, AstNode content, TokenPosition position) : base(flags, content, position) { valueLocal = null; }
public void SetSelfLocal(LocalVariable local) { selfLocal = local; }
public override AstNode Visit(FixedVariableDecl node) { // Get the variable type. IChelaType type = node.GetNodeType(); // Create the variable. LocalVariable fixedVar = new LocalVariable(node.GetName(), (LexicalScope)currentScope, type); node.SetVariable(fixedVar); // Visit the value expression. Expression valueExpr = node.GetValueExpression(); valueExpr.Accept(this); // Get the value type. IChelaType valueType = valueExpr.GetNodeType(); // The value must be a reference or a pointer. if(!valueType.IsReference() && !valueType.IsPointer()) Error(valueExpr, "the value expression must be a reference or a pointer."); if(valueType.IsPointer()) { if(Coerce(node, type, valueType, valueExpr.GetNodeValue()) != type) Error(valueExpr, "cannot convert {0} into {1}.", valueType.GetName(), type.GetName()); // Coerce the value. node.SetCoercionType(type); } else { // Remove references. IChelaType refType = DeReferenceType(valueType); if(refType.IsReference()) refType = DeReferenceType(refType); // Only support arrays if(refType.IsArray()) { ArrayType array = (ArrayType)refType; IChelaType pointerType = PointerType.Create(array.GetValueType()); if(Coerce(node, type, pointerType, null) != type) Error(valueExpr, "cannot convert {0} into {1}.", pointerType.GetName(), type.GetName()); } // Set the new coercion type. node.SetCoercionType(ReferenceType.Create(refType)); } return node; }