public override int Emit(ProtoCore.AST.Node codeBlockNode, ProtoCore.AssociativeGraph.GraphNode graphNode = null) { if (core.Options.IsDeltaExecution) { if (context != null && context.symbolTable != null) { Validity.Assert(context.symbolTable.symbolList != null && context.symbolTable.symbolList.Count > 0); codeBlock.symbolTable = context.symbolTable; } } AllocateContextGlobals(); core.watchStartPC = this.pc; if (core.Options.RunMode == ProtoCore.DSASM.InterpreterMode.kExpressionInterpreter) { return EmitExpressionInterpreter(codeBlockNode); } this.localCodeBlockNode = codeBlockNode; ProtoCore.AST.AssociativeAST.CodeBlockNode codeblock = codeBlockNode as ProtoCore.AST.AssociativeAST.CodeBlockNode; bool isTopBlock = null == codeBlock.parent; if (!isTopBlock) { // If this is an inner block where there can be no classes, we can start at parsing at the global function state compilePass = ProtoCore.CompilerDefinitions.Associative.CompilePass.kGlobalFuncSig; } codeblock.Body = ApplyTransform(codeblock.Body); bool hasReturnStatement = false; ProtoCore.Type inferedType = new ProtoCore.Type(); bool ssaTransformed = false; while (ProtoCore.CompilerDefinitions.Associative.CompilePass.kDone != compilePass) { // Emit SSA only after generating the class definitions if (core.Options.GenerateSSA) { if (compilePass > ProtoCore.CompilerDefinitions.Associative.CompilePass.kClassName && !ssaTransformed) { if (!core.IsParsingCodeBlockNode && !core.Options.IsDeltaExecution) { //Audit class table for multiple symbol definition and emit warning. this.core.ClassTable.AuditMultipleDefinition(this.core.BuildStatus, graphNode); } codeblock.Body = BuildSSA(codeblock.Body, context); ssaTransformed = true; if (core.Options.DumpIL) { CodeGenDS codegenDS = new CodeGenDS(codeblock.Body); EmitCompileLog(codegenDS.GenerateCode()); } } } inferedType = TypeSystem.BuildPrimitiveTypeObject(PrimitiveType.kTypeVar, 0); hasReturnStatement = EmitCodeBlock(codeblock.Body, ref inferedType, ProtoCore.CompilerDefinitions.Associative.SubCompilePass.kUnboundIdentifier, false); if (compilePass == ProtoCore.CompilerDefinitions.Associative.CompilePass.kGlobalScope && !hasReturnStatement) { EmitReturnNull(); } compilePass++; // We have compiled all classes if (compilePass == ProtoCore.CompilerDefinitions.Associative.CompilePass.kGlobalScope && isTopBlock) { EmitFunctionCallToInitStaticProperty(codeblock.Body); } } ResolveFinalNodeRefs(); ResolveSSADependencies(); ProtoCore.AssociativeEngine.Utils.BuildGraphNodeDependencies( codeBlock.instrStream.dependencyGraph.GetGraphNodesAtScope(Constants.kInvalidIndex, Constants.kGlobalScope)); if (codeBlock.parent == null) // top-most langauge block { ResolveFunctionGroups(); } core.InferedType = inferedType; if (core.AsmOutput != Console.Out) { core.AsmOutput.Flush(); } this.localCodeBlockNode = codeBlockNode; // Reset the callsite guids in preparation for the next compilation core.CallsiteGuidMap = new Dictionary<Guid, int>(); return codeBlock.codeBlockId; }
public override int Emit(ProtoCore.AST.Node codeBlockNode, ProtoCore.AssociativeGraph.GraphNode graphNode = null) { if (compileStateTracker.Options.IsDeltaExecution) { if (context != null && context.symbolTable != null) { Validity.Assert(context.symbolTable.symbolList != null && context.symbolTable.symbolList.Count > 0); codeBlock.symbolTable = context.symbolTable; } } AllocateContextGlobals(); compileStateTracker.startPC = this.pc; if (compileStateTracker.ExecMode == ProtoCore.DSASM.InterpreterMode.kExpressionInterpreter) { return EmitExpressionInterpreter(codeBlockNode); } this.localCodeBlockNode = codeBlockNode; ProtoCore.AST.AssociativeAST.CodeBlockNode codeblock = codeBlockNode as ProtoCore.AST.AssociativeAST.CodeBlockNode; bool isTopBlock = null == codeBlock.parent; if (!isTopBlock) { // If this is an inner block where there can be no classes, we can start at parsing at the global function state compilePass = ProtoCore.DSASM.AssociativeCompilePass.kGlobalFuncSig; } codeblock.Body = SplitMulitpleAssignment(codeblock.Body); codeblock.Body = BuildSSA(codeblock.Body, context); if (compileStateTracker.Options.DumpIL) { CodeGenDS codegenDS = new CodeGenDS(codeblock.Body); EmitCompileLog(codegenDS.GenerateCode()); } bool hasReturnStatement = false; ProtoCore.Type inferedType = new ProtoCore.Type(); while (ProtoCore.DSASM.AssociativeCompilePass.kDone != compilePass) { foreach (AssociativeNode node in codeblock.Body) { inferedType = new ProtoCore.Type(); inferedType.UID = (int)ProtoCore.PrimitiveType.kTypeVar; inferedType.IsIndexable = false; // // TODO Jun: Handle stand alone language blocks // Integrate the subPass into a proper pass // // **Need to take care of EmitImportNode, in which I used the same code to handle imported language block nodes - Randy // if (node is LanguageBlockNode) { // Build a binaryn node with a temporary lhs for every stand-alone language block var iNode = nodeBuilder.BuildIdentfier(compileStateTracker.GenerateTempLangageVar()); var langBlockNode = nodeBuilder.BuildBinaryExpression(iNode, node); DfsTraverse(langBlockNode, ref inferedType, false, graphNode, ProtoCore.DSASM.AssociativeSubCompilePass.kUnboundIdentifier); } else { DfsTraverse(node, ref inferedType, false, graphNode, ProtoCore.DSASM.AssociativeSubCompilePass.kUnboundIdentifier); SetDeltaCompilePC(node); } if (NodeUtils.IsReturnExpressionNode(node)) hasReturnStatement = true; } if (compilePass == ProtoCore.DSASM.AssociativeCompilePass.kGlobalScope && !hasReturnStatement) { EmitReturnNull(); } compilePass++; // We have compiled all classes if (compilePass == ProtoCore.DSASM.AssociativeCompilePass.kGlobalScope && isTopBlock) { EmitFunctionCallToInitStaticProperty(codeblock.Body); } } ResolveFinalNodeRefs(); if (codeBlock.parent == null) // top-most langauge block { ResolveFunctionGroups(); } compileStateTracker.InferedType = inferedType; if (compileStateTracker.AsmOutput != Console.Out) { compileStateTracker.AsmOutput.Flush(); } this.localCodeBlockNode = codeBlockNode; return codeBlock.codeBlockId; }
/// <summary> /// Resets the VM whenever a new library is imported and re-imports them /// Returns the list of new Library Mirrors for reflection /// TODO: It should not be needed once we have language support to insert import statements arbitrarily /// </summary> /// <param name="libraries"></param> /// <returns></returns> public List<LibraryMirror> ResetVMAndImportLibrary(List<string> libraries) { List<LibraryMirror> libs = new List<LibraryMirror>(); // Reset VM ReInitializeLiveRunner(); // generate import node for each library in input list List<AssociativeNode> importNodes = null; foreach (string lib in libraries) { importNodes = new List<AssociativeNode>(); ProtoCore.AST.AssociativeAST.ImportNode importNode = new ProtoCore.AST.AssociativeAST.ImportNode(); importNode.ModuleName = lib; importNodes.Add(importNode); ProtoCore.CodeGenDS codeGen = new ProtoCore.CodeGenDS(importNodes); string code = codeGen.GenerateCode(); int currentCI = runnerCore.ClassTable.ClassNodes.Count; UpdateCmdLineInterpreter(code); int postCI = runnerCore.ClassTable.ClassNodes.Count; IList<ProtoCore.DSASM.ClassNode> classNodes = new List<ProtoCore.DSASM.ClassNode>(); for (int i = currentCI; i < postCI; ++i) { classNodes.Add(runnerCore.ClassTable.ClassNodes[i]); } ProtoCore.Mirror.LibraryMirror libraryMirror = ProtoCore.Mirror.Reflection.Reflect(lib, classNodes, runnerCore); libs.Add(libraryMirror); } return libs; }
/// <summary> /// This is called temporarily to reset the VM and recompile the entire graph with new import /// statements whenever a node from a new library is added to the graph. /// TODO: It should not be needed once we have language support to insert import statements arbitrarily /// </summary> /// <param name="libraries"></param> /// <param name="syncData"></param> public void ResetVMAndResyncGraph(IEnumerable<string> libraries) { // Reset VM ReInitializeLiveRunner(); if (!libraries.Any()) { return; } // generate import node for each library in input list List<AssociativeNode> importNodes = new List<AssociativeNode>(); foreach (string lib in libraries) { ProtoCore.AST.AssociativeAST.ImportNode importNode = new ProtoCore.AST.AssociativeAST.ImportNode(); importNode.ModuleName = lib; importNodes.Add(importNode); } ProtoCore.CodeGenDS codeGen = new ProtoCore.CodeGenDS(importNodes); string code = codeGen.GenerateCode(); UpdateCmdLineInterpreter(code); }
/// <summary> /// This is to be used for debugging only to check code emitted from delta AST input /// </summary> /// <param name="deltaAstList"></param> /// <returns></returns> private string DebugCodeEmittedForDeltaAst(List<AssociativeNode> deltaAstList) { var codeGen = new ProtoCore.CodeGenDS(deltaAstList); var code = codeGen.GenerateCode(); return code; }
public override int Emit(ProtoCore.AST.Node codeBlockNode, ProtoCore.AssociativeGraph.GraphNode graphNode = null) { if (core.Options.IsDeltaExecution) { if (context != null && context.symbolTable != null) { Validity.Assert(context.symbolTable.symbolList != null && context.symbolTable.symbolList.Count > 0); codeBlock.symbolTable = context.symbolTable; } } AllocateContextGlobals(); core.startPC = this.pc; if (core.ExecMode == ProtoCore.DSASM.InterpreterMode.kExpressionInterpreter) { return EmitExpressionInterpreter(codeBlockNode); } this.localCodeBlockNode = codeBlockNode; ProtoCore.AST.AssociativeAST.CodeBlockNode codeblock = codeBlockNode as ProtoCore.AST.AssociativeAST.CodeBlockNode; bool isTopBlock = null == codeBlock.parent; if (!isTopBlock) { // If this is an inner block where there can be no classes, we can start at parsing at the global function state compilePass = ProtoCore.DSASM.AssociativeCompilePass.kGlobalFuncSig; } codeblock.Body = SplitMulitpleAssignment(codeblock.Body); bool hasReturnStatement = false; ProtoCore.Type inferedType = new ProtoCore.Type(); bool ssaTransformed = false; while (ProtoCore.DSASM.AssociativeCompilePass.kDone != compilePass) { // Emit SSA only after generating the class definitions if (core.Options.GenerateSSA) { if (compilePass > AssociativeCompilePass.kClassName && !ssaTransformed) { if (!core.IsParsingCodeBlockNode && !core.Options.IsDeltaExecution) { //Audit class table for multiple symbol definition and emit warning. this.core.ClassTable.AuditMultipleDefinition(this.core.BuildStatus, graphNode == null ? default(Guid) : graphNode.guid); } codeblock.Body = BuildSSA(codeblock.Body, context); core.CachedSSANodes.Clear(); core.CachedSSANodes.AddRange(codeblock.Body); ssaTransformed = true; if (core.Options.DumpIL) { CodeGenDS codegenDS = new CodeGenDS(codeblock.Body); EmitCompileLog(codegenDS.GenerateCode()); } } } foreach (AssociativeNode node in codeblock.Body) { inferedType = TypeSystem.BuildPrimitiveTypeObject(PrimitiveType.kTypeVar, 0); // // TODO Jun: Handle stand alone language blocks // Integrate the subPass into a proper pass // // **Need to take care of EmitImportNode, in which I used the same code to handle imported language block nodes - Randy // if (node is LanguageBlockNode) { // Build a binaryn node with a temporary lhs for every stand-alone language block var iNode = nodeBuilder.BuildIdentfier(core.GenerateTempLangageVar()); var langBlockNode = nodeBuilder.BuildBinaryExpression(iNode, node); DfsTraverse(langBlockNode, ref inferedType, false, graphNode, ProtoCore.DSASM.AssociativeSubCompilePass.kUnboundIdentifier); } else { DfsTraverse(node, ref inferedType, false, graphNode, ProtoCore.DSASM.AssociativeSubCompilePass.kUnboundIdentifier); SetDeltaCompilePC(node); } if (NodeUtils.IsReturnExpressionNode(node)) hasReturnStatement = true; } if (compilePass == ProtoCore.DSASM.AssociativeCompilePass.kGlobalScope && !hasReturnStatement) { EmitReturnNull(); } compilePass++; // We have compiled all classes if (compilePass == ProtoCore.DSASM.AssociativeCompilePass.kGlobalScope && isTopBlock) { EmitFunctionCallToInitStaticProperty(codeblock.Body); } } ResolveFinalNodeRefs(); ResolveSSADependencies(); if (codeBlock.parent == null) // top-most langauge block { ResolveFunctionGroups(); } core.InferedType = inferedType; if (core.AsmOutput != Console.Out) { core.AsmOutput.Flush(); } this.localCodeBlockNode = codeBlockNode; // Reset the callsite guids in preparation for the next compilation core.CallsiteGuidMap = new Dictionary<Guid, int>(); return codeBlock.codeBlockId; }