Example #1
0
        static int Main(string[] args)
        {
            string source   = "";
            string target   = "";
            string filename = "";

            bool addFunctions = false;

            if (args.Length < 2)
            {
                Console.WriteLine("SucCompiler by sucklead (http://dcotetools.sucklead.com/p/succompiler.html)");
                Console.WriteLine("Version [{0}]", Assembly.GetExecutingAssembly().GetName().Version);
                Console.WriteLine();
                Console.WriteLine("To compile a single file");
                Console.WriteLine("SucCompiler {source directory} {binary directory} {source filename}");
                Console.WriteLine(@"e.g. To compile src\gamescripts\01_house\$debug\debugblack.hfs into directory bin");
                Console.WriteLine("from directory scripts:");
                Console.WriteLine(@"SucCompiler src bin gamescripts\01_house\$debug\debugblack.hfs");
                Console.WriteLine();
                Console.WriteLine("To compile all file in a directory");
                Console.WriteLine("SucCompiler {source directory} {binary directory}");
                Console.WriteLine("e.g. to compile everything in src to bin");
                Console.WriteLine("from directory scripts:");
                Console.WriteLine("SucCompiler src bin");
                Console.WriteLine();
                Console.WriteLine("Easiest way to run it is from within the Scripts directory:");
                Console.WriteLine("SucCompiler src newbin");
                return(-1);
            }

            //set source and target
            source = args[0].Replace("/", "\\");
            target = args[1].Replace("/", "\\");;

            Console.WriteLine("SucCompiler by sucklead started at {0}", DateTime.Now);
            Console.WriteLine("Version [{0}]", Assembly.GetExecutingAssembly().GetName().Version);
            Console.WriteLine("Source -> {0}", source);
            Console.WriteLine("Target -> {0}", target);

            //addfunctions parameter?
            //if (args.Length > 3)
            //{
            //    if (bool.TryParse(args[1], out addFunctions))
            //    {
            //        addFunctions = false;
            //    }
            //}

            ////debug a script?
            //if (Debugger.IsAttached)
            //{
            //    Directory.SetCurrentDirectory(@"F:\Games\Call Of Cthulhu DCoTE\Scripts");

            //    filename = @"gamescripts\06_refinery\animatedreachtargets\goldvault\goldvaultsouthvalveturn.bin";
            //    //addFunctions = true;
            //}

            FunctionTable.LoadData();

            //set the options
            Compiler compiler = new Compiler();

            compiler.AddFunctions    = addFunctions;
            compiler.SourceDirectory = source;
            compiler.TargetDirectory = target;

            if (args.Length > 2)
            {
                for (int a = 2; a < args.Length; a++)
                {
                    filename = args[a].Replace("/", "\\");;
                    if (filename.StartsWith(source))
                    {
                        filename = filename.Substring(source.Length + 1);
                    }

                    //convert to windows
                    if (File.Exists(Path.Combine(source, filename)))
                    {
                        compiler.CompileFile(filename);
                    }
                    else
                    {
                        Console.WriteLine("ERROR: Compile source {0} does not exist", Path.Combine(source, filename));
                        return(-2);
                    }
                }
            }
            else
            {
                filename = "";
                if (Directory.Exists(source))
                {
                    compiler.CompileDirectory(source);
                }
                else
                {
                    Console.WriteLine("ERROR: Compile source {0} does not exist", source);
                    return(-3);
                }
            }
            //save function table if anything has changed
            FunctionTable.SaveData();

            Console.WriteLine("Compile completed at {0}.", DateTime.Now);
            //Console.WriteLine("\n\nPress <Enter> to exit..");
            //Console.ReadLine();
            return(0);
        }
Example #2
0
        private void CompileNode(SyntaxNode node)
        {
            //if (node is GlobalStatementSyntax)
            //{
            //GlobalStatementSyntax globalStatement = node as GlobalStatementSyntax;

            if (node is GlobalStatementSyntax)
            {
                node = ((GlobalStatementSyntax)node).Statement;
            }

            if (node is BlockSyntax)
            {
                BlockSyntax block = node as BlockSyntax;
                foreach (StatementSyntax statement in block.Statements)
                {
                    CompileNode(statement);
                }
            }
            else if (node is ParenthesizedExpressionSyntax)
            {
                ParenthesizedExpressionSyntax parenthesizedExpression = node as ParenthesizedExpressionSyntax;

                CompileNode(parenthesizedExpression.Expression);

                if (node.Parent.Kind() == SyntaxKind.LogicalNotExpression || // TODO - check this still works
                    node.Parent.Kind() == SyntaxKind.BitwiseNotExpression ||
                    node.Parent.Kind() == SyntaxKind.UnaryMinusExpression)
                {
                    OP_NEG opNeg = new OP_NEG();
                    OpCodes.Add(opNeg);
                }
            }
            else if (node is ExpressionStatementSyntax)
            {
                ExpressionStatementSyntax expressionStatement = node as ExpressionStatementSyntax;

                CompileNode(expressionStatement.Expression);
            }
            else if (node is LiteralExpressionSyntax)
            {
                LiteralExpressionSyntax literalExpression = node as LiteralExpressionSyntax;

                OP_PUSH opPush = new OP_PUSH();
                opPush.DataIndex = Literals[literalExpression].Address;
                OpCodes.Add(opPush);

                if (Literals[literalExpression].IsNegative)
                {
                    //push a negative on top
                    OP_NEG opNeg = new OP_NEG();
                    OpCodes.Add(opNeg);
                }
            }
            //else if (node is null)
            //{

            //}
            else if (node is PrefixUnaryExpressionSyntax)
            {
                PrefixUnaryExpressionSyntax prefixUnaryExpression = node as PrefixUnaryExpressionSyntax;
                //a not? negatives are handled later
                if (prefixUnaryExpression.Kind() == SyntaxKind.LogicalNotExpression)
                {
                    CompileNode(prefixUnaryExpression.Operand);

                    //add a not
                    OP_NOT opNot = new OP_NOT();
                    OpCodes.Add(opNot);
                }
                else
                {
                    CompileNode(prefixUnaryExpression.Operand);
                }
            }
            else if (node is IdentifierNameSyntax)
            {
                IdentifierNameSyntax identifierName = node as IdentifierNameSyntax;

                OP_PUSH opPush = new OP_PUSH();
                if (identifierName != null)
                {
                    opPush.DataIndex = Variables[identifierName.ToString()].Address; // TODO check this  .PlainName
                }
                OpCodes.Add(opPush);

                if (node.Parent.Kind() == SyntaxKind.UnaryMinusExpression) // TODO - check this
                {
                    //add a not
                    OP_NEG opNeg = new OP_NEG();
                    OpCodes.Add(opNeg);
                }
            }
            else if (node is ArgumentSyntax)
            {
                ArgumentSyntax argument = node as ArgumentSyntax;

                if (argument.Expression is PrefixUnaryExpressionSyntax)
                {
                    //for a negative parse the operand
                    PrefixUnaryExpressionSyntax prefixUnaryExpression = argument.Expression as PrefixUnaryExpressionSyntax;
                    CompileNode(prefixUnaryExpression.Operand);
                }
                //if (argument.Expression is LiteralExpressionSyntax
                //    || argument.Expression is IdentifierNameSyntax)
                else
                {
                    CompileNode(argument.Expression);
                }
            }
            //a function invocation
            else if (node is InvocationExpressionSyntax)
            {
                InvocationExpressionSyntax invocationExpressionSyntax = node as InvocationExpressionSyntax;

                //first we have an identifier expression
                IdentifierNameSyntax identifierNameSyntax = invocationExpressionSyntax.Expression as IdentifierNameSyntax;

                //then arguments
                foreach (ArgumentSyntax argumentSyntax in invocationExpressionSyntax.ArgumentList.Arguments) //TODO .Reverse()?
                {
                    //Console.WriteLine("    [Literal]");
                    //Console.WriteLine("    " + (LiteralExpressionSyntax)(argumentSyntax.Expression));
                    CompileNode(argumentSyntax);
                }

                if (identifierNameSyntax.ToString() == "Print")
                {
                    OP_PRINT opPrint = new OP_PRINT();
                    OpCodes.Add(opPrint);
                }
                else
                {
                    //push the function code
                    OP_PUSH opPush = new OP_PUSH();

                    if (!FunctionTable.Functions.ContainsKey(identifierNameSyntax.ToString()))
                    {
                        if (!this.AddFunctions && !this.justPatchFunctions)
                        {
                            hasMissingFunctions = true;

                            //if (!this.DirectoryBased)
                            if (true)
                            {
                                Console.WriteLine(string.Format("Missing function {0}", identifierNameSyntax.ToString()));
                            }
                            opPush.DataIndex = 0x0FF0;
                        }
                        else
                        {
                            Console.WriteLine(string.Format("Fetching function {0}", identifierNameSyntax.ToString()));

                            short functionPointer = FunctionTable.FindFunction(this.ScriptFilename.Replace(".hfs", ".bin"), identifierNameSyntax.ToString(), opPush.Address + 1);

                            opPush.DataIndex = functionPointer;
                        }
                    }
                    else
                    {
                        opPush.DataIndex = FunctionTable.Functions[identifierNameSyntax.ToString()];
                    }
                    OpCodes.Add(opPush);

                    //add function call
                    OP_FUNCTION opFunction = new OP_FUNCTION();
                    OpCodes.Add(opFunction);

                    //do a discard
                    if (node.Parent is BinaryExpressionSyntax ||
                        node.Parent is AssignmentExpressionSyntax)
                    {
                    }
                    else
                    {
                        OP_DISCARD opDiscard = new OP_DISCARD();
                        OpCodes.Add(opDiscard);
                    }
                }
            }
            else if (node is AssignmentExpressionSyntax)
            {
                AssignmentExpressionSyntax assignmentExpression = node as AssignmentExpressionSyntax;
                CompileNode(assignmentExpression.Right);

                IdentifierNameSyntax identifierName = assignmentExpression.Left as IdentifierNameSyntax;

                //gettop the left
                OP_GETTOP opGettop = new OP_GETTOP();
                opGettop.DataIndex = Variables[identifierName.ToString()].Address;
                OpCodes.Add(opGettop);

                //for an if we need to keep the value
                //or for a double assign
                if (assignmentExpression.Parent.Kind() != SyntaxKind.IfStatement &&
                    assignmentExpression.Parent.Kind() != SyntaxKind.SimpleAssignmentExpression)
                {
                    //do a discard
                    OP_DISCARD opDiscard = new OP_DISCARD();
                    OpCodes.Add(opDiscard);
                }
            }
            else if (node is BinaryExpressionSyntax)
            {
                BinaryExpressionSyntax binaryExpression = node as BinaryExpressionSyntax;
                if (binaryExpression.OperatorToken.Kind() == SyntaxKind.EqualsToken)
                {
                    CompileNode(binaryExpression.Right);

                    IdentifierNameSyntax identifierName = binaryExpression.Left as IdentifierNameSyntax;

                    //gettop the left
                    OP_GETTOP opGettop = new OP_GETTOP();
                    opGettop.DataIndex = Variables[identifierName.ToString()].Address;
                    OpCodes.Add(opGettop);

                    //for an if we need to keep the value
                    if (binaryExpression.Parent.Kind() != SyntaxKind.IfStatement)
                    {
                        //do a discard
                        OP_DISCARD opDiscard = new OP_DISCARD();
                        OpCodes.Add(opDiscard);
                    }
                }
                else if (binaryExpression.OperatorToken.Kind() == SyntaxKind.EqualsEqualsToken)
                {
                    CompileNode(binaryExpression.Left);

                    CompileNode(binaryExpression.Right);

                    OP_EQUAL opEqual = new OP_EQUAL();
                    OpCodes.Add(opEqual);

                    if (node.Parent.Kind() == SyntaxKind.ExpressionStatement)
                    {
                        //just discard the result
                        OP_DISCARD opDiscard = new OP_DISCARD();
                        OpCodes.Add(opDiscard);
                    }
                }
                else if (binaryExpression.OperatorToken.Kind() == SyntaxKind.ExclamationEqualsToken)
                {
                    CompileNode(binaryExpression.Left);

                    CompileNode(binaryExpression.Right);

                    OP_NOT_EQUAL opNotEqual = new OP_NOT_EQUAL();
                    OpCodes.Add(opNotEqual);
                }
                else if (binaryExpression.OperatorToken.Kind() == SyntaxKind.MinusToken)
                {
                    CompileNode(binaryExpression.Left);

                    CompileNode(binaryExpression.Right);

                    OP_MINUS opEqual = new OP_MINUS();
                    OpCodes.Add(opEqual);
                }
                else if (binaryExpression.OperatorToken.Kind() == SyntaxKind.PlusToken)
                {
                    CompileNode(binaryExpression.Left);

                    CompileNode(binaryExpression.Right);

                    OP_CONCAT opEqual = new OP_CONCAT();
                    OpCodes.Add(opEqual);
                }
                else if (binaryExpression.OperatorToken.Kind() == SyntaxKind.GreaterThanToken)
                {
                    CompileNode(binaryExpression.Left);

                    CompileNode(binaryExpression.Right);

                    OP_MORE_THAN opEqual = new OP_MORE_THAN();
                    OpCodes.Add(opEqual);
                }
                else if (binaryExpression.OperatorToken.Kind() == SyntaxKind.LessThanToken)
                {
                    CompileNode(binaryExpression.Left);

                    CompileNode(binaryExpression.Right);

                    OP_LESS_THAN opEqual = new OP_LESS_THAN();
                    OpCodes.Add(opEqual);
                }
                else if (binaryExpression.OperatorToken.Kind() == SyntaxKind.LessThanEqualsToken)
                {
                    CompileNode(binaryExpression.Left);

                    CompileNode(binaryExpression.Right);

                    OP_LESS_THAN_OR_EQUAL opLessOrEqual = new OP_LESS_THAN_OR_EQUAL();
                    OpCodes.Add(opLessOrEqual);
                }
                else if (binaryExpression.OperatorToken.Kind() == SyntaxKind.GreaterThanEqualsToken)
                {
                    CompileNode(binaryExpression.Left);

                    CompileNode(binaryExpression.Right);

                    OP_MORE_THAN_OR_EQUAL opGreatOrEqual = new OP_MORE_THAN_OR_EQUAL();
                    OpCodes.Add(opGreatOrEqual);
                }
                else if (binaryExpression.OperatorToken.Kind() == SyntaxKind.BarBarToken)
                {
                    CompileNode(binaryExpression.Left);

                    CompileNode(binaryExpression.Right);

                    OP_OR opOr = new OP_OR();
                    OpCodes.Add(opOr);
                }
                else if (binaryExpression.OperatorToken.Kind() == SyntaxKind.AmpersandAmpersandToken)
                {
                    CompileNode(binaryExpression.Left);

                    CompileNode(binaryExpression.Right);

                    OP_AND opAnd = new OP_AND();
                    OpCodes.Add(opAnd);
                }
                else if (binaryExpression.OperatorToken.Kind() == SyntaxKind.AsteriskToken)
                {
                    CompileNode(binaryExpression.Left);

                    CompileNode(binaryExpression.Right);

                    OP_MULTIPLY opMultiply = new OP_MULTIPLY();
                    OpCodes.Add(opMultiply);
                }
                else if (binaryExpression.OperatorToken.Kind() == SyntaxKind.SlashToken)
                {
                    CompileNode(binaryExpression.Left);

                    CompileNode(binaryExpression.Right);

                    OP_DIVIDE opDivide = new OP_DIVIDE();
                    OpCodes.Add(opDivide);
                }
            }
            else if (node is WhileStatementSyntax)
            {
                WhileStatementSyntax whileStatement = node as WhileStatementSyntax;

                short whileAddress = OpCode.NextAddress;

                CompileNode(whileStatement.Condition);

                //look at the condition here
                OP_JMPF opJmpF = new OP_JMPF();
                OpCodes.Add(opJmpF);

                CompileNode(whileStatement.Statement);

                //jmp back to the condition
                OP_JMP opJmp = new OP_JMP();
                opJmp.DataIndex = whileAddress;
                OpCodes.Add(opJmp);

                //jump over the jmp back
                opJmpF.DataIndex = (short)(opJmp.Address + 3);
            }
            else if (node is IfStatementSyntax)
            {
                IfStatementSyntax ifStatement = node as IfStatementSyntax;

                //look at the condition here
                CompileNode(ifStatement.Condition);

                short ifAddress = OpCode.NextAddress;
                //do a jump to end if condition is false
                OP_JMPF opJmpF = new OP_JMPF();
                OpCodes.Add(opJmpF);

                CompileNode(ifStatement.Statement);

                //has an else option?
                if (ifStatement.Else != null) //TODO - check this works
                {
                    OP_JMP opJmp = new OP_JMP();
                    OpCodes.Add(opJmp);

                    //save this as the else jump so we can hook it up later
                    this.ElseJmps.Push(opJmp);
                }

                //add in the jump target
                JUMPTARGET jumpTarget = new JUMPTARGET();
                jumpTarget.DataIndex = ifAddress;
                OpCodes.Add(jumpTarget);

                //jump is to here
                opJmpF.DataIndex = jumpTarget.Address;

                CompileNode(ifStatement.Else);
            }
            else if (node is ElseClauseSyntax)
            {
                ElseClauseSyntax elseClause = node as ElseClauseSyntax;

                CompileNode(elseClause.Statement);

                //pop off last one
                OP_JMP opJmp = this.ElseJmps.Pop();

                //add in the jump target
                JUMPTARGET jumpTarget = new JUMPTARGET();
                jumpTarget.DataIndex = opJmp.Address;
                OpCodes.Add(jumpTarget);

                //jump is to here
                opJmp.DataIndex = jumpTarget.Address;
            }

            //}
            //else if (node is BlockSyntax)
            //{
            //    BlockSyntax block = node as BlockSyntax;
            //    foreach (StatementSyntax statement in block.Statements)
            //    {
            //        CompileNode(statement);
            //    }
            //}
        }