コード例 #1
0
ファイル: AST.cs プロジェクト: Reavenk/SynthSyntax
        public AST(Token t, SynNestingBuilder builder, ASTOp ast, SynObj so, SynType sevty, bool hasAddress, DataManifest manifest, int ptrDepth, params AST [] branches)
        {
            this.builder        = builder;
            this.synthObj       = so;
            this.evaluatingType = sevty;
            this.token          = t;
            this.astType        = ast;
            this.hasAddress     = hasAddress;
            this.manifest       = manifest;
            this.ptrDepth       = ptrDepth;

            this.branches = new List <AST>(); // Should we always allocate this?
            if (branches != null && branches.Length > 0)
            {
                this.branches.AddRange(branches);
            }
        }
コード例 #2
0
ファイル: SynType.cs プロジェクト: Reavenk/SynthSyntax
 public virtual SynFuncDecl GetCopyConstructor(bool autocreate, SynNestingBuilder scb) => null;
コード例 #3
0
        // TODO: Perhaps this function should be moved into WASMBuild?
        public SynNestingBuilder BuildFunction(SynFuncDecl fnd)
        {
            SynNestingBuilder builder = new SynNestingBuilder(null);

            if (fnd.ast != null)
            {
                throw new SynthExceptionImpossible($"Attempting to build function {fnd.functionName} AST multiple times.");
            }

            SynLog.Log($"Entered SynthFuncDecl.Build() for {fnd.functionName}.");

            // NOTE: For now functions are non-typed (in the SynthSyn language) and
            // are non addressable.
            fnd.ast =
                new AST(
                    fnd.declPhrase[0],
                    builder,
                    ASTOp.FunctionDecl,
                    fnd,
                    null,
                    false,
                    AST.DataManifest.NoData);

            SynLog.Log($"Building function AST for {fnd.functionName}.");
            SynLog.Log("");

            List <SynNestingBuilder> builders = new List <SynNestingBuilder>();

            builders.Add(builder);

            //List<TokenTree> treeLines = new List<TokenTree>();
            for (int i = 0; i < fnd.executingLines.Count; ++i)
            {
                List <Token> execLine = fnd.executingLines[i];
                SynLog.LogFragments(execLine);

                TokenTree rootLineNode = TokenTree.EatTokensIntoTree(execLine, fnd, true);

                SynLog.LogTree(rootLineNode);

                // If it's a member function (not a static function) then full in the struct
                // we belong to as a he invoking scope. Or else set it to null. Its syntax scope
                // it still all the way where the source code is, but doesn't have a "this" member
                // function.
                SynScope invokingScope = null;
                if (fnd.isStatic == false)
                {
                    invokingScope = fnd.GetStructScope();
                }

                AST exprAST = builder.ProcessFunctionExpression(builders, this, invokingScope, fnd, rootLineNode);
                if (exprAST == null)
                {
                    // We shouldn't have received null, we should have thrown before this
                    throw new SynthExceptionImpossible(""); //TODO:
                }
                fnd.ast.branches.Add(exprAST);
            }
            fnd.ast.branches.Add(new AST(new Token(), builder, ASTOp.EndScope, builder, null, false, AST.DataManifest.NoData));

            SynLog.Log("");
            SynLog.Log($"Encountered {builders.Count} nested scopes.");
            for (int i = 0; i < builders.Count; ++i)
            {
                SynLog.LogIndent(0, $"Scope {i}");
                SynLog.LogIndent(1, $"Line number : {builders[i].lineNumber}");
                SynLog.LogIndent(1, $"Stack Elements : Ele {builders[i].locStkEle.Count} - Vars {builders[i].locStkVars.Count}");
                SynLog.LogIndent(1, $"Memory Stack : Vars {builders[i].memStkVars.Count}");
                SynLog.LogIndent(1, $"Total Memory Stack : Bytes {builders[i].totalMemoryStackBytes}");
            }

            SynLog.Log("");
            SynLog.Log(fnd.ast.DumpDiagnostic());

            SynLog.Log($"Finished building AST : {fnd.functionName}.");
            SynLog.Log($"Converting AST to binary WASM : {fnd.functionName}.");

            // Before the AST is turned into actual WASM binary, we need to finalize the
            // byte alignment and the indices of local stack variables. This is done with
            // CompileAlignment, who's lower scopes should appear earlier in the builders
            // list before higher children scopes.
            for (int i = 0; i < builders.Count; ++i)
            {
                if (i == 0)
                {
                    builders[i].CompileAlignment(fnd);
                }
                else
                {
                    builders[i].CompileAlignment();
                }
            }

            // Gather all the local variables and declare them. This isn't as efficient as things
            // could be because after variables go out of scope, their positions on the stack
            // can be reused if they match types we encounter in the future, but that can be
            // handled later.

            // The program binary
            WASMByteBuilder fnBuild = new WASMByteBuilder();

            // Gather all the local variables
            List <WASM.Bin.TypeID> localVarTys = new List <WASM.Bin.TypeID>();

            foreach (SynNestingBuilder b in builders)
            {
                foreach (ValueRef stkVal in b.locStkEle)
                {
                    if (stkVal.varType.intrinsic == false)
                    {
                        throw new SynthExceptionCompile(""); // TODO: Error msg
                    }
                    switch (stkVal.varType.typeName)
                    {
                    case "bool":
                    case "int8":
                    case "uint8":
                    case "int16":
                    case "uint16":
                    case "int":
                    case "int32":
                        localVarTys.Add(WASM.Bin.TypeID.Int32);
                        break;

                    case "int64":
                    case "uint64":
                        localVarTys.Add(WASM.Bin.TypeID.Int64);
                        break;

                    case "float":
                        localVarTys.Add(WASM.Bin.TypeID.Float32);
                        break;

                    case "double":
                        localVarTys.Add(WASM.Bin.TypeID.Float64);
                        break;
                    }
                }
            }

            List <KeyValuePair <WASM.Bin.TypeID, int> > consolidatedLocalTys = new List <KeyValuePair <WASM.Bin.TypeID, int> >();

            for (int i = 0; i < localVarTys.Count; ++i)
            {
                WASM.Bin.TypeID tyid = localVarTys[i];
                int             ct   = 1;
                ++i;

                for (; i < localVarTys.Count; ++i)
                {
                    if (localVarTys[i] != tyid)
                    {
                        break;
                    }

                    ++ct;
                }
                consolidatedLocalTys.Add(new KeyValuePair <WASM.Bin.TypeID, int>(tyid, ct));
            }

            fnBuild.AddLEB128((uint)consolidatedLocalTys.Count); // Local decl
            for (int i = 0; i < consolidatedLocalTys.Count; ++i)
            {
                fnBuild.AddLEB128((uint)consolidatedLocalTys[i].Value);

                // These are really bytes, but they'll end up being added as bytes since they're
                // small constants
                fnBuild.AddLEB128((uint)consolidatedLocalTys[i].Key);
            }

            builder.BuildBSFunction(fnd, fnd.ast, this, builder, fnBuild);
            fnBuild.Add_End();
            fnd.fnBin = fnBuild.Bin();

            SynLog.Log($"Exiting SynthFuncDecl.Build({fnd.functionName}).");
            return(builder);
        }
コード例 #4
0
ファイル: SynStruct.cs プロジェクト: Reavenk/SynthSyntax
        /// <summary>
        /// This function is expected to be called during AST construction
        /// (of whatever needs the copy constructor). This means struct
        /// processing and alignment should have already occured. This also
        /// means the function will be queued for being constructed into
        /// WASM binary like all other functions in a later pass.
        /// </summary>
        /// <param name="autocreate">If the function doesn't exist, auto
        /// create a default copy constructor and register it with the struct.
        /// </param>
        /// <returns>The found, or created, copy constructor for the struct.</returns>
        public override SynFuncDecl GetCopyConstructor(bool autocreate, SynNestingBuilder scb)
        {
            List <SynFuncDecl> lstFns;

            if (this.functions.TryGetValue(this.typeName, out lstFns) == false)
            {
                if (autocreate == false)
                {
                    return(null);
                }

                // If we're autocreating, prepare a list for it to be registered in.
                lstFns = new List <SynFuncDecl>();
                this.functions.Add(this.typeName, lstFns);
            }
            else
            {
                foreach (SynFuncDecl fns in lstFns)
                {
                    if (fns.returnType != null)
                    {
                        continue;
                    }

                    if (fns.parameterSet.Count != 2)
                    {
                        continue;
                    }

                    if (
                        fns.parameterSet.Get(0).type != this ||
                        fns.parameterSet.Get(1).type != this)
                    {
                        continue;
                    }

                    return(fns);
                }

                if (autocreate == false)
                {
                    return(null);
                }
            }

            SynFuncDecl sfdCC = new SynFuncDecl(this);
            //
            SynVarValue svvDst = new SynVarValue();

            svvDst.varLoc   = SynVarValue.VarLocation.ThisRef;
            svvDst.dataType = SynVarValue.VarValueDataType.Pointer;
            //
            SynVarValue svvSrc = new SynVarValue();

            svvSrc.varLoc   = SynVarValue.VarLocation.Parameter;
            svvSrc.dataType = SynVarValue.VarValueDataType.Reference;

            sfdCC.parameterSet.AddParameter(svvDst);
            sfdCC.parameterSet.AddParameter(svvSrc);

            // TODO: Do explicit alignment here?

            // Add this ahead of time
            lstFns.Add(sfdCC);

            // Go through each variable in order and copy them by producing the proper AST
            for (int i = 0; i < this.varDefs.Count; ++i)
            {
                SynVarValue svv = this.varDefs[i];    // The member to copy

                if (svv.type.intrinsic == true)
                {
                    AST astSrcDeref     = new AST(new Token(-1, svv.varName, TokenType.tyWord), scb, ASTOp.DerefName, null, svv.type, false, AST.DataManifest.Procedural, 0);
                    AST astSrcGetMember = new AST(new Token(), scb, ASTOp.GetMemberVar, svvSrc, this, false, AST.DataManifest.Procedural, 0, astSrcDeref);

                    AST astDstDeref     = new AST(new Token(-1, svv.varName, TokenType.tyWord), scb, ASTOp.DerefName, null, svv.type, false, AST.DataManifest.Procedural, 0);
                    AST astDstGetMember = new AST(new Token(), scb, ASTOp.GetMemberVar, svvSrc, this, false, AST.DataManifest.Procedural, 0, astSrcDeref);

                    AST astSetVar = new AST(new Token(), scb, ASTOp.SetValue, null, null, false, AST.DataManifest.NoData, 0, astSrcDeref, astSrcGetMember);
                    sfdCC.ast.branches.Add(astSetVar);
                }
                else
                {
                    // Else, it's a sub-struct, and we use GetCopyConstructor() recursively
                    // to copy it.
                    throw new SynthExceptionCompile("Class copy constructors are not supported.");
                }
            }

            return(sfdCC);
        }