Ejemplo n.º 1
0
        private int GeneratePrimitive(AstPrimitive ast)
        {
            if (primitivesTable == null)
            {
                primitivesTable = new Dictionary <Symbol, PrimCodegenItem>();

                DefinePrimitiveCodegen("+", GenerateArith2, OpCode.ADD);
                DefinePrimitiveCodegen("-", GenerateArith2, OpCode.SUB);
                DefinePrimitiveCodegen("*", GenerateArith2, OpCode.MUL);
                DefinePrimitiveCodegen("/", GenerateArith2, OpCode.DIV);
                DefinePrimitiveCodegen("%", GenerateArith2, OpCode.MOD);
                DefinePrimitiveCodegen("=", GenerateArith2, OpCode.EQ);
                DefinePrimitiveCodegen(">", GenerateArith2, OpCode.GT);
                DefinePrimitiveCodegen("<", GenerateArith2, OpCode.LT);
                DefinePrimitiveCodegen("!=", GenerateArith2, OpCode.NE);
                DefinePrimitiveCodegen(">=", GenerateArith2, OpCode.GE);
                DefinePrimitiveCodegen("<=", GenerateArith2, OpCode.LE);
                DefinePrimitiveCodegen("pow", GenerateArith2, OpCode.POW);
                DefinePrimitiveCodegen("and", GenerateAndOr, OpCode.AND);
                DefinePrimitiveCodegen("or", GenerateAndOr, OpCode.OR);
                DefinePrimitiveCodegen("neg", GenerateArith1, OpCode.NEG);
                DefinePrimitiveCodegen("not", GenerateArith1, OpCode.NOT);
                DefinePrimitiveCodegen("len", GenerateArith1, OpCode.LEN);
                DefinePrimitiveCodegen("concat", GenerateArithX, OpCode.CONCAT);
            }
            var sym = ast.Identifier.AsIdentifier();

            var prim = primitivesTable[sym];

            return(prim.method(ast, prim.opcode));
        }
Ejemplo n.º 2
0
        // two arguments primitive.
        // more that two arguments will be raped to list of primitives
        // (foo 1 2)
        public static AST Expand(Syntax stx, Environment env)
        {
            var list = stx.AsLinkedList <Value>();
            var argc = GetArgsCount(list);

            AssertArgsMinimum("primitive2", "arity mismatch", 2, argc, list, stx);
            var set_kwd   = list[0].AsSyntax();
            var arguments = AstBuilder.ExpandListElements(list, 1, env);

            if (argc == 2)
            {
                return(new AstPrimitive(stx, set_kwd, arguments));
            }
            else
            {
                // for expression (+ 1 2 3 4)
                var args     = arguments.DuplicateReverse(0, -1); //< (+ 4 3 2 1)
                var rightarg = args[0];                           //< 4
                var skip     = 1;
                foreach (var leftarg in args)                     //< 3, 2, 1,
                {
                    if (skip-- > 0)
                    {
                        continue;
                    }
                    var values = ValueLinkedList.FromArguments(leftarg, rightarg);
                    var prim   = new AstPrimitive(stx, set_kwd, values);
                    rightarg.Set(prim);
                }
                return(rightarg.AsAST());
            }
        }
Ejemplo n.º 3
0
        /// <summary>
        /// This is the code generator for abstract opcode
        /// </summary>
        /// <param name="ast"></param>
        /// <param name="opcode"></param>
        /// <returns></returns>
        internal int GenerateArith2(AstPrimitive ast, OpCode opcode)
        {
            var temp = Push();

            var args = ast.Arguments;
            int arg0 = Generate(args[0].AsAST());
            int arg1 = Generate(args[1].AsAST());

            AddABC(opcode, temp, (byte)arg0, (byte)arg1);

            SP = temp;
            return(temp);
        }
Ejemplo n.º 4
0
        /// <summary>
        /// This is the code generator for abstract opcode
        /// </summary>
        /// <param name="ast"></param>
        /// <param name="opcode"></param>
        /// <returns></returns>
        internal int GenerateArith1(AstPrimitive ast, OpCode opcode)
        {
            var result = Push();
            var args   = ast.Arguments;

            foreach (var arg in args)
            {
                var expres = Generate(arg.AsAST());
                AddAB(opcode, result, expres);
                Pop();
            }
            SP = result;
            return(result);
        }
Ejemplo n.º 5
0
        /// <summary>
        /// This is the code generator for abstract opcode
        /// </summary>
        /// <param name="ast"></param>
        /// <param name="opcode"></param>
        /// <returns></returns>
        internal int GenerateArithX(AstPrimitive ast, OpCode opcode)
        {
            // R(A) := R(B) .. ... .. R(C)

            var temp = (short)(SP + 1);

            var args = ast.Arguments;

            foreach (var arg in args)
            {
                var res = Generate(arg.AsAST());
                if (res < SpMin)
                {
                    /// Case if it is addressed directly to the variable
                    /// MOVE R(A) := R(B)
                    AddAB(OpCode.MOVE, Push(), res);
                }
            }
            AddABC(OpCode.CONCAT, temp, temp, (short)(temp + args.Count - 1));
            SP = temp;
            return(temp);
        }
Ejemplo n.º 6
0
        /// <summary>
        /// This is the code generator for abstract opcode
        /// different with arithmetics is the first expression
        /// returns true will terminate execution
        /// </summary>
        /// <param name="ast"></param>
        /// <param name="opcode"></param>
        /// <returns></returns>
        internal int GenerateAndOr(AstPrimitive ast, OpCode opcode)
        {
            var isOrOperation = opcode == OpCode.OR;
            var expected      = isOrOperation ? (short)1 : (short)0;
            /// This is the arguments list
            var args = ast.Arguments;
            /// Here will be jump instruction position for each argument
            var jumps = new int[args.Count];
            /// Put result to this value
            var result = Push();

            for (var i = 0; i < args.Count; i++)
            {
                var argpos = Generate(args[i].AsAST());
                /// =======================================================
                /// if (R(B).AsBool == (bool)C)
                ///     {skip next instruction}
                /// else
                ///     R(A) = R(B)
                /// =======================================================
                AddABC(OpCode.TESTSET, result, argpos, expected);
                jumps[i] = AddOpcode(Instruction.Nop);
                Pop();
            }
            Code.Add(Instruction.MakeAB(OpCode.LOADBOOL, result, isOrOperation ? (short)0 : (short)1));

            /// now make all jumps to the
            var pc = PC;

            foreach (var jmp in jumps)
            {
                Code[jmp] = Instruction.MakeASBX(OpCode.JMP, 0, Jmp(jmp, pc));
            }

            SP = result;
            return(result);
        }