예제 #1
0
 public object visit_assign(AssignExpr assign_expression)
 {
     resolve(assign_expression.value);
     // Resolve the variable to the interpreter
     resolve_local_position(assign_expression, assign_expression.name);
     return(null);
 }
예제 #2
0
        /// <summary>
        /// Assign a value to an expression.
        /// </summary>
        /// <param name="expr">The assignment expressions</param>
        /// <returns></returns>
        public object VisitAssign(AssignExpr expr)
        {
            var ctx           = expr.Ctx;
            var varExpr       = expr.VarExp;
            var valueExpr     = expr.ValueExp;
            var node          = expr;
            var isDeclaration = expr.IsDeclaration;

            // CASE 1: Assign variable.  a = 1
            if (varExpr.IsNodeType(NodeTypes.SysVariable))
            {
                AssignHelper.SetVariableValue(ctx, this, node, isDeclaration, varExpr, valueExpr);
            }
            // CASE 2: Assign member.
            //      e.g. dictionary       :  user.name = 'kishore'
            //      e.g. property on class:  user.age  = 20
            else if (varExpr.IsNodeType(NodeTypes.SysMemberAccess))
            {
                AssignHelper.SetMemberValue(ctx, this, node, varExpr, valueExpr);
            }
            // Case 3: Assign value to index: "users[0]" = <expression>;
            else if (varExpr.IsNodeType(NodeTypes.SysIndex))
            {
                AssignHelper.SetIndexValue(ctx, this, node, varExpr, valueExpr);
            }
            return(LObjects.Null);
        }
예제 #3
0
        public override IUnboundExpr Transform(AssignExpr expr)
        {
            // replaces:
            //
            //     a, b <- Foo
            //
            // with:
            //
            //     def __temp1 <- Foo
            //     a <- _temp1.0
            //     b <- _temp1.1

            TupleExpr tuple = expr.Target as TupleExpr;

            // ignore other assignments
            if (tuple == null) return expr;

            var exprs = new List<IUnboundExpr>();

            var temp = mNameGenerator.Generate();

            // evaluate the right-hand side once
            exprs.Add(new DefineExpr(expr.Target.Position, temp, expr.Value, false));

            // split out the fields
            int index = 0;
            foreach (var field in tuple.Fields)
            {
                exprs.Add(new AssignExpr(expr.Position, field, new CallExpr(new IntExpr(index), new NameExpr(expr.Position, temp))));
                index++;
            }

            return new BlockExpr(false, exprs);
        }
예제 #4
0
        public override void Visit(AssignExpr expr)
        {
            expr.value.Accept(this);
            ushort addr = chunk.AddConstant(new Value(expr.name.lexeme));

            chunk.WriteOpCode(OpCode.SET_GLOBAL);
            chunk.WriteWord(addr);
        }
예제 #5
0
 /// <summary>
 /// Visits the var statement tree.
 /// </summary>
 /// <param name="assignExpr"></param>
 public void Var(AssignExpr assignExpr)
 {
     _callBack(assignExpr);
     foreach (var decl in assignExpr._declarations)
     {
         Visit(decl.Item1);
         Visit(decl.Item2);
     }
 }
예제 #6
0
        public override void Visit(AssignExpr expr)
        {
            string tempStr = expr.name.lexeme;

            AddStr(expr.name.lexeme);
            AddStr(" = ");

            expr.value.Accept(this);
        }
예제 #7
0
 /// <summary>
 /// Visits the var statement tree.
 /// </summary>
 /// <param name="expr"></param>
 public object VisitAssign(AssignExpr expr)
 {
     _callBackOnNodeStart(expr);
     expr.VarExp.Visit(this);
     if (expr.ValueExp != null)
     {
         expr.ValueExp.Visit(this);
     }
     return(null);
 }
예제 #8
0
        /// <summary>
        /// Creates a unary expression with symbol scope, context, script refernce set.
        /// </summary>
        /// <param name="name"></param>
        /// <param name="token"></param>
        /// <returns></returns>
        public static Expr Assign(bool declare, Expr left, Expr right, TokenData token)
        {
            var exp = new AssignExpr();

            exp.IsDeclaration = declare;
            exp.VarExp        = left;
            exp.ValueExp      = right;
            SetupContext(exp, token);
            return(exp);
        }
예제 #9
0
        private void Assign(Memory memory, string name, object val, bool isConst, object expected)
        {
            var ctx = new Context();

            ctx.Memory = memory;
            Expr expr = isConst
                            ? (Expr) new ConstantExpr(val)
                            : (Expr) new VariableExpr(val.ToString());
            var exp = new AssignExpr(true, name, expr);

            expr.Ctx = ctx;
            exp.Ctx  = ctx;
            exp.Evaluate();
            Assert.AreEqual(expected, memory.GetAs <LObject>(name).GetValue());
        }
예제 #10
0
    public object visit_assign(AssignExpr assign_expression)
    {
        object value = evaluate(assign_expression.value);

        // If the value is assigning to a local variable, then set it
        if (local_depths.ContainsKey(assign_expression))
        {
            int distance = local_depths[assign_expression];
            local_scope.assign_at(distance, assign_expression.name, value);
        }
        // Else the value is assigning to a global
        else
        {
            global_scope.assign(assign_expression.name, value);
        }
        return(value);
    }
예제 #11
0
        Arg ApplyUsualConversions(ArgList args, out Expr writeBack)
        {
            writeBack = null;
            bool hasRefArgs = false;

            for (int i = 0; i < args.Args.Count; i++)
            {
                var e = args.Args[i].Expr;
                Convert(ref e, Compilation.Get(NativeType.Usual));
                if (args.Args[i].RefKind != RefKind.None)
                {
                    hasRefArgs = true;
                }
            }
            var arguments = new Arg(LiteralArray.Bound(args.Args));

            if (hasRefArgs)
            {
                var conv = ConversionSymbol.Create(ConversionSymbol.Create(ConversionKind.Identity), new ConversionToTemp(arguments.Expr.Datatype));
                Convert(ref arguments.Expr, arguments.Expr.Datatype, conv);
                for (int i = 0; i < args.Args.Count; i++)
                {
                    if (args.Args[i].RefKind != RefKind.None)
                    {
                        HandleVarArgWriteBack(conv, args.Args[i].Expr, i, ref writeBack);
                    }
                }
            }
            return(arguments);

            void HandleVarArgWriteBack(ConversionSymbol conv, Expr e, int i, ref Expr wb)
            {
                if (e.Symbol?.HasSetAccess == true || e is AutoVarExpr || e is AliasExpr)
                {
                    // Handle writeBack
                    Expr t = IdExpr.Bound(conv.IndirectRefConversionTempLocal());
                    t = ArrayAccessExpr.Bound(t, ArgList.Bound(LiteralExpr.Bound(Constant.Create(i + 1))), this);
                    var wc = Conversion(t, e.Datatype, BindOptions.Default);
                    if (wc.Exists)
                    {
                        Convert(ref t, e.Datatype, wc);
                        SymbolExtensions.AddExpr(ref wb, AssignExpr.Bound(e, t, BindOptions.Default));
                    }
                }
            }
        }
예제 #12
0
        internal ForStmt ParseForStmt()
        {
            Token t;

            ExpectAndGet(TokenType.FOR, out t);
            VarDecl    d = null;
            AssignExpr a = null;

            if (ExpectAny(TokenType.IMPLIED, TokenType.VAR) || (La(2) == TokenType.IMPLIED && Expect(TokenType.LOCAL) && Expect(TokenType.IMPLIED)))
            {
                d = ParseForDecl(true);
            }
            else if (Expect(TokenType.LOCAL))
            {
                d = ParseForDecl(false);
            }
            else
            {
                a = ParseExpression() as AssignExpr;
                Require(a?.Left is IdExpr, ErrorCode.Expected, "variable assignemnt expression");
            }
            var  dir   = Require(ExpectAndGetAny(TokenType.UPTO, TokenType.DOWNTO, TokenType.TO), ErrorCode.Expected, TokenType.TO);
            Expr final = RequireExpression();
            Expr step  = null;

            if (Expect(TokenType.STEP))
            {
                step = RequireExpression();
            }
            Require(TokenType.EOS);
            var s = ParseStatementBlock();

            if (Expect(TokenType.END))
            {
                Expect(TokenType.FOR);
            }
            else
            {
                Require(Expect(TokenType.NEXT), ErrorCode.Expected, "END FOR");
            }
            Require(TokenType.EOS);
            return(a != null ? new ForStmt(t, a, dir, final, step, s)
                : new ForStmt(t, d, dir, final, step, s));
        }
예제 #13
0
        public void Visit(AssignExpr assignExpr, object[] args)
        {
            assignExpr.LeftExpr.Accept(this);
            assignExpr.RightExpr.Accept(this);

            RightValue v = readRightValue(assignExpr.RightExpr);

            assignExpr.RightValue = v;

            if (assignExpr.LeftExpr.LeftValue is VarRef)
            {
                VarRef varRef = assignExpr.LeftExpr.LeftValue as VarRef;
                scopeStack.SetValue(varRef.VarName, v);
            }
            else
            {
                throw new Exception();
            }
        }
    public object visit_assign(AssignExpr assign_expression)
    {
        //Console.WriteLine("visiting assign: " + assign_expression.name.value+", "+local_scope.get(new Token(Token.Type.Identifier,"x")));
        object value = evaluate(assign_expression.value);

        //Console.WriteLine("new value: "+value);
        // If the value is assigning to a local variable, then set it
        if (local_depths.ContainsKey(assign_expression))
        {
            int distance = local_depths[assign_expression];
            local_scope.assign_at(distance, assign_expression.name, value);
        }
        // Else the value is assigning to a global
        else
        {
            global_scope.assign(assign_expression.name, value);
        }
        return(value);
    }
예제 #15
0
        public void Can_Validate_Variable_Does_Not_Exist()
        {
            var symScope = new Symbols();

            symScope.DefineVariable("result");

            var semacts = new SemActs();
            var a       = new VariableExpr("a");

            a.Ref      = new ScriptRef("", 1, 1);
            a.SymScope = symScope.Current;

            var zero = new ConstantExpr(2);

            zero.Ref      = new ScriptRef("", 1, 5);
            zero.SymScope = symScope.Current;

            var divExpr = new BinaryExpr(a, Operator.Divide, zero);

            divExpr.SymScope = symScope.Current;

            var assignExpr = new AssignExpr(true, new VariableExpr("result"), divExpr);

            assignExpr.SymScope = symScope.Current;
            var stmts = new List <Expr>();

            stmts.Add(assignExpr);

            var success = semacts.Validate(stmts);
            var results = semacts.Results;

            Assert.IsFalse(success);
            Assert.IsFalse(results.Success);
            Assert.IsTrue(results.HasResults);
            Assert.AreEqual(results.Results.Count, 1);
        }
예제 #16
0
 public virtual void Visit(AssignExpr expr)
 {
 }
        public void Visit(AssignExpr assignExpr, object[] args)
        {
            assignExpr.LeftExpr.Accept(this);
            assignExpr.RightExpr.Accept(this);

            RightValue v = readRightValue(assignExpr.RightExpr);
            assignExpr.RightValue = v;

            if (assignExpr.LeftExpr.LeftValue is VarRef)
            {
                VarRef varRef = assignExpr.LeftExpr.LeftValue as VarRef;
                scopeStack.SetValue(varRef.VarName, v);
            }
            else
            {
                throw new Exception();
            }
        }
예제 #18
0
        /// <summary>
        /// end表示字符串最后一个字符的后一个位置
        /// </summary>
        /// <param name="begin"></param>
        /// <param name="end"></param>
        /// <returns></returns>
        private Expression parse(int begin, int end)
        {
            if (begin >= end)
            {
                kernel.IssueError(ErrorType.ExpressionSyntaxError, loc.Offset(begin));
                return(null);
            }

            while (isWhiteSpace(expr[begin]))
            {
                begin++;
            }
            while (isWhiteSpace(expr[end - 1]))
            {
                end--;
            }

            int  currentParenLevel;
            bool hasSideParren = true;

            while (expr[begin] == '(' && hasSideParren)
            {
                currentParenLevel = 0;
                int currentPos;
                for (currentPos = begin; currentPos < end; currentPos++)
                {
                    if (expr[currentPos] == '(')
                    {
                        currentParenLevel++;
                    }
                    else if (expr[currentPos] == ')')
                    {
                        currentParenLevel--;
                        if (currentParenLevel == 0)
                        {
                            if (currentPos == end - 1)
                            {
                                begin++;
                                end--;
                            }
                            else
                            {
                                hasSideParren = false;
                            }
                            break;
                        }
                    }
                }

                if (currentPos == end && currentParenLevel > 0)
                {
                    kernel.IssueError(ErrorType.SingleParen, loc.Offset(begin));
                    return(null);
                }
            }

            currentParenLevel = 0;
            OpLevel          currentLevel = OpLevel.Null;
            OpLevel          minLevel     = OpLevel.Null;
            int              minPos       = -1;
            int              minOpLength  = 0;
            bool             findOp       = false;
            string           op           = null;
            MatchTokenResult matchTokenResult;

            //找到当前应处理的操作符
            for (int currentPos = begin; currentPos < end; currentPos = matchTokenResult.EndPos)
            {
                //if (expr[currentPos] == ' ' || expr[currentPos] == '\t' || expr[currentPos] == '\n'
                //    || Environment.NewLine.IndexOf(expr[currentPos]) != -1)
                //{
                //    op = null;
                //    continue;
                //}

                matchTokenResult = MatchToken(currentPos, end);
                if (matchTokenResult.TokenType == TokenType.Error)
                {
                    return(null);
                }

                if (matchTokenResult.TokenType != TokenType.Operator)
                {
                    continue;
                }

                op = matchTokenResult.Matched;

                if (op != "(" && op != ")")
                {
                    findOp = true;
                }
                if (op == "(")
                {
                    currentParenLevel++;
                    continue;
                }
                else if (op == ")")
                {
                    currentParenLevel--;
                    continue;
                }
                else if (currentParenLevel > 0)
                {
                    continue;
                }
                else if (currentParenLevel < 0)
                {
                    kernel.IssueError(ErrorType.SingleParen, loc.Offset(currentPos));
                    return(null);
                }

                if (currentParenLevel == 0 &&
                    (
                        (int)(currentLevel = getOpLevel(op)) < (int)minLevel) ||
                    ((int)currentLevel == (int)minLevel && op != "=")       //=为右结合
                    )
                {
                    minLevel    = currentLevel;
                    minPos      = matchTokenResult.BeginPos;
                    minOpLength = op.Length;
                }
            }

            if (currentParenLevel != 0)
            {
                kernel.IssueError(ErrorType.SingleParen, loc.Offset(begin));
                return(null);
            }

            if (!findOp)    //单个数据
            {
                string str        = expr.Substring(begin, end - begin);
                int    currentPos = begin;
                matchTokenResult = MatchToken(currentPos, end);

                switch (matchTokenResult.TokenType)
                {
                case TokenType.Int:
                    RightValueExpr intResult = new RightValueExpr();
                    IntConst       intConst  = new IntConst();
                    intConst.Value       = int.Parse(matchTokenResult.Matched);
                    intResult.DataType   = DataType.Int;
                    intResult.RightValue = intConst;
                    intResult.Location   = loc.Offset(begin);
                    return(intResult);

                case TokenType.Float:
                    RightValueExpr floatResult = new RightValueExpr();
                    FloatConst     floatConst  = new FloatConst();
                    floatConst.Value       = float.Parse(matchTokenResult.Matched);
                    floatResult.DataType   = DataType.Float;    //modified by Wander @ 2011
                    floatResult.RightValue = floatConst;
                    floatResult.Location   = loc.Offset(begin);
                    return(floatResult);

                case TokenType.String:
                    RightValueExpr strResult = new RightValueExpr();
                    StringConst    strConst  = new StringConst();
                    strConst.Value       = matchTokenResult.Matched;
                    strResult.DataType   = DataType.String;
                    strResult.RightValue = strConst;
                    strResult.Location   = loc.Offset(begin);
                    return(strResult);

                case TokenType.Bool:
                    RightValueExpr boolResult = new RightValueExpr();
                    BoolConst      boolConst  = new BoolConst();
                    boolConst.Value       = bool.Parse(matchTokenResult.Matched);
                    boolResult.DataType   = DataType.Bool;
                    boolResult.RightValue = boolConst;
                    boolResult.Location   = loc.Offset(begin);
                    return(boolResult);

                case TokenType.Variable:
                    VarRef varRef = new VarRef();
                    varRef.VarName = matchTokenResult.Matched;
                    LeftValueExpr leftValueResult = new LeftValueExpr();
                    leftValueResult.DataType  = DataType.Unknown;
                    leftValueResult.Location  = loc.Offset(begin);
                    leftValueResult.LeftValue = varRef;
                    return(leftValueResult);

                default:
                    kernel.IssueError(ErrorType.ExpressionSyntaxError, loc.Offset(begin));
                    return(null);
                }
            }

            Expression left;
            Expression right;

            matchTokenResult = MatchToken(minPos, end);
            op = matchTokenResult.Matched;

            left  = (begin != minPos) ? parse(begin, minPos) : null; //null表示单目运算符
            right = parse(matchTokenResult.EndPos, end);
            Location currentLoc = loc.Offset(begin);

            if (right == null)
            {
                return(null);
            }


            switch (op)
            {
            case "=":
                if (!(left is LeftValueExpr))
                {
                    kernel.IssueError(ErrorType.NotLeftValue, currentLoc);
                    return(null);
                }
                AssignExpr assignExpr = new AssignExpr();
                assignExpr.LeftExpr  = left as LeftValueExpr;
                assignExpr.RightExpr = right;
                assignExpr.DataType  = right.DataType;
                assignExpr.Location  = currentLoc;
                return(assignExpr);

            case "&&":
                return(processBinaryLogicExpr(
                           new AndExpr(),
                           left, right, currentLoc));


            case "||":
                return(processBinaryLogicExpr(
                           new OrExpr(),
                           left, right, currentLoc));

            case "==":
                return(processBinaryCmpExpr(new EquExpr(), left, right, currentLoc));

            case "!=":
                return(processBinaryCmpExpr(new NeqExpr(), left, right, currentLoc));

            case ">":
                return(processBinaryCmpExpr(new GreatExpr(), left, right, currentLoc));

            case ">=":
                return(processBinaryCmpExpr(new GreatEquExpr(), left, right, currentLoc));

            case "<":
                return(processBinaryCmpExpr(new LessExpr(), left, right, currentLoc));

            case "<=":
                return(processBinaryCmpExpr(new LessEquExpr(), left, right, currentLoc));

            case "+":
                return(processBinaryAlgoExpr(new AddExpr(), left, right, currentLoc));

            case "-":
                if (left == null)
                {
                    NegativeExpr negExpr = new NegativeExpr();
                    if (right.DataType == DataType.Bool || right.DataType == DataType.String)
                    {
                        kernel.IssueError(ErrorType.OprandTypeError, currentLoc);
                        return(null);
                    }
                    else if (right.DataType == DataType.Int)
                    {
                        negExpr.DataType = DataType.Int;
                    }
                    else if (right.DataType == DataType.Float)
                    {
                        negExpr.DataType = DataType.Float;
                    }
                    else
                    {
                        negExpr.DataType = DataType.Unknown;
                    }


                    negExpr.Op       = right;
                    negExpr.Location = currentLoc;
                    return(negExpr);
                }
                else
                {
                    return(processBinaryAlgoExpr(new SubExpr(), left, right, currentLoc));
                }

            case "*":
                return(processBinaryAlgoExpr(new MulExpr(), left, right, currentLoc));

            case "/":
                return(processBinaryAlgoExpr(new DivExpr(), left, right, currentLoc));

            case "^":
                return(processBinaryAlgoExpr(new PowExpr(), left, right, currentLoc));

            case "!":
                if (left != null)
                {
                    kernel.IssueError(ErrorType.ExpressionSyntaxError, currentLoc);
                    return(null);
                }
                else
                {
                    NotExpr notExpr = new NotExpr();
                    notExpr.DataType = DataType.Bool;
                    notExpr.Op       = right;
                    notExpr.Location = currentLoc;
                    return(notExpr);
                }
            }

            return(null);
        }
        /// <summary>
        /// end表示字符串最后一个字符的后一个位置
        /// </summary>
        /// <param name="begin"></param>
        /// <param name="end"></param>
        /// <returns></returns>
        private Expression parse(int begin, int end)
        {
            if (begin >= end)
            {
                kernel.IssueError(ErrorType.ExpressionSyntaxError, loc.Offset(begin));
                return null;
            }

            while (isWhiteSpace(expr[begin]))
                begin++;
            while (isWhiteSpace(expr[end - 1]))
                end--;

            int currentParenLevel;
            bool hasSideParren = true;
            while (expr[begin] == '(' && hasSideParren)
            {
                currentParenLevel = 0;
                int currentPos;
                for (currentPos = begin; currentPos < end; currentPos++)
                {
                    if (expr[currentPos] == '(') currentParenLevel++;
                    else if (expr[currentPos] == ')')
                    {
                        currentParenLevel--;
                        if (currentParenLevel == 0)
                        {
                            if (currentPos == end - 1)
                            {
                                begin++;
                                end--;
                            }
                            else
                                hasSideParren = false;
                            break;
                        }
                    }
                }

                if (currentPos == end && currentParenLevel > 0)
                {
                    kernel.IssueError(ErrorType.SingleParen, loc.Offset(begin));
                    return null;
                }
            }

            currentParenLevel = 0;
            OpLevel currentLevel = OpLevel.Null;
            OpLevel minLevel = OpLevel.Null;
            int minPos = -1;
            int minOpLength = 0;
            bool findOp = false;
            string op = null;
            MatchTokenResult matchTokenResult;

            //找到当前应处理的操作符
            for (int currentPos = begin; currentPos < end; currentPos = matchTokenResult.EndPos)
            {
                //if (expr[currentPos] == ' ' || expr[currentPos] == '\t' || expr[currentPos] == '\n'
                //    || Environment.NewLine.IndexOf(expr[currentPos]) != -1)
                //{
                //    op = null;
                //    continue;
                //}

                matchTokenResult = MatchToken(currentPos, end);
                if (matchTokenResult.TokenType == TokenType.Error)
                    return null;

                if (matchTokenResult.TokenType != TokenType.Operator)
                    continue;

                op = matchTokenResult.Matched;

                if (op != "(" && op != ")") findOp = true;
                if (op == "(")
                {
                    currentParenLevel++;
                    continue;
                }
                else if (op == ")")
                {
                    currentParenLevel--;
                    continue;
                }
                else if (currentParenLevel > 0)
                {
                    continue;
                }
                else if (currentParenLevel < 0)
                {
                    kernel.IssueError(ErrorType.SingleParen, loc.Offset(currentPos));
                    return null;
                }

                if (currentParenLevel == 0
                    &&(
                    (int)(currentLevel = getOpLevel(op)) < (int)minLevel)
                    || ((int)currentLevel == (int)minLevel && op != "=")    //=为右结合
                    )
                {
                    minLevel = currentLevel;
                    minPos = matchTokenResult.BeginPos;
                    minOpLength = op.Length;
                }
            }

            if (currentParenLevel != 0)
            {
                kernel.IssueError(ErrorType.SingleParen, loc.Offset(begin));
                return null;
            }

            if (!findOp)    //单个数据
            {
                string str = expr.Substring(begin, end - begin);
                int currentPos = begin;
                matchTokenResult = MatchToken(currentPos, end);

                switch (matchTokenResult.TokenType)
                {
                    case TokenType.Int:
                        RightValueExpr intResult = new RightValueExpr();
                        IntConst intConst = new IntConst();
                        intConst.Value = int.Parse(matchTokenResult.Matched);
                        intResult.DataType = DataType.Int;
                        intResult.RightValue = intConst;
                        intResult.Location = loc.Offset(begin);
                        return intResult;

                    case TokenType.Float:
                        RightValueExpr floatResult = new RightValueExpr();
                        FloatConst floatConst = new FloatConst();
                        floatConst.Value = float.Parse(matchTokenResult.Matched);
                        floatResult.DataType = DataType.Int;
                        floatResult.RightValue = floatConst;
                        floatResult.Location = loc.Offset(begin);
                        return floatResult;

                    case TokenType.String:
                        RightValueExpr strResult = new RightValueExpr();
                        StringConst strConst = new StringConst();
                        strConst.Value = matchTokenResult.Matched;
                        strResult.DataType = DataType.String;
                        strResult.RightValue = strConst;
                        strResult.Location = loc.Offset(begin);
                        return strResult;

                    case TokenType.Bool:
                        RightValueExpr boolResult = new RightValueExpr();
                        BoolConst boolConst = new BoolConst();
                        boolConst.Value = bool.Parse(matchTokenResult.Matched);
                        boolResult.DataType = DataType.Bool;
                        boolResult.RightValue = boolConst;
                        boolResult.Location = loc.Offset(begin);
                        return boolResult;

                    case TokenType.Variable:
                        VarRef varRef = new VarRef();
                        varRef.VarName = matchTokenResult.Matched;
                        LeftValueExpr leftValueResult = new LeftValueExpr();
                        leftValueResult.DataType = DataType.Unknown;
                        leftValueResult.Location = loc.Offset(begin);
                        leftValueResult.LeftValue = varRef;
                        return leftValueResult;

                    default:
                        kernel.IssueError(ErrorType.ExpressionSyntaxError, loc.Offset(begin));
                        return null;
                }
            }

            Expression left;
            Expression right;

            matchTokenResult = MatchToken(minPos, end);
            op = matchTokenResult.Matched;

            left = (begin != minPos) ? parse(begin, minPos) : null; //null表示单目运算符
            right = parse(matchTokenResult.EndPos, end);
            Location currentLoc = loc.Offset(begin);

            if (right == null)
                return null;

            switch (op)
            {
                case "=":
                    if (!(left is LeftValueExpr))
                    {
                        kernel.IssueError(ErrorType.NotLeftValue, currentLoc);
                        return null;
                    }
                    AssignExpr assignExpr = new AssignExpr();
                    assignExpr.LeftExpr = left as LeftValueExpr;
                    assignExpr.RightExpr = right;
                    assignExpr.DataType = right.DataType;
                    assignExpr.Location = currentLoc;
                    return assignExpr;

                case "&&":
                    return processBinaryLogicExpr(
                        new AndExpr(),
                        left, right, currentLoc);

                case "||":
                    return processBinaryLogicExpr(
                        new OrExpr(),
                        left, right, currentLoc);

                case "==":
                    return processBinaryCmpExpr(new EquExpr(), left, right, currentLoc);

                case "!=":
                    return processBinaryCmpExpr(new NeqExpr(), left, right, currentLoc);

                case ">":
                    return processBinaryCmpExpr(new GreatExpr(), left, right, currentLoc);

                case ">=":
                    return processBinaryCmpExpr(new GreatEquExpr(), left, right, currentLoc);

                case "<":
                    return processBinaryCmpExpr(new LessExpr(), left, right, currentLoc);

                case "<=":
                    return processBinaryCmpExpr(new LessEquExpr(), left, right, currentLoc);

                case "+":
                    return processBinaryAlgoExpr(new AddExpr(), left, right, currentLoc);

                case "-":
                    if (left == null)
                    {
                        NegativeExpr negExpr = new NegativeExpr();
                        if (right.DataType == DataType.Bool || right.DataType == DataType.String)
                        {
                            kernel.IssueError(ErrorType.OprandTypeError, currentLoc);
                            return null;
                        }
                        else if (right.DataType == DataType.Int)
                        {
                            negExpr.DataType = DataType.Int;
                        }
                        else if (right.DataType == DataType.Float)
                        {
                            negExpr.DataType = DataType.Float;
                        }
                        else
                        {
                            negExpr.DataType = DataType.Unknown;
                        }

                        negExpr.Op = right;
                        negExpr.Location = currentLoc;
                        return negExpr;
                    }
                    else
                    {
                        return processBinaryAlgoExpr(new SubExpr(), left, right, currentLoc);
                    }

                case "*":
                    return processBinaryAlgoExpr(new MulExpr(), left, right, currentLoc);

                case "/":
                    return processBinaryAlgoExpr(new DivExpr(), left, right, currentLoc);

                case "^":
                    return processBinaryAlgoExpr(new PowExpr(), left, right, currentLoc);

                case "!":
                    if (left != null)
                    {
                        kernel.IssueError(ErrorType.ExpressionSyntaxError, currentLoc);
                        return null;
                    }
                    else
                    {
                        NotExpr notExpr = new NotExpr();
                        notExpr.DataType = DataType.Bool;
                        notExpr.Op = right;
                        notExpr.Location = currentLoc;
                        return notExpr;
                    }
            }

            return null;
        }
예제 #20
0
        void ApplyConversions(ArgList args, OverloadResult ovRes, out Expr writeBack)
        {
            writeBack = null;
            var parameters = ovRes.Parameters.Parameters;

            for (int i = 0; i < ovRes.FixedArgs; i++)
            {
                var conv = ovRes.Conversions[i];
                var e    = args.Args[i].Expr;
                if (conv.Kind != ConversionKind.Identity)
                {
                    Convert(ref args.Args[i].Expr, FindType(parameters[i].ParameterType), conv);
                }
                if (conv is ConversionSymbolToConstant)
                {
                    Convert(ref args.Args[i].Expr, FindType(parameters[i].ParameterType), BindOptions.Default);
                }
                HandleArgWriteBack(conv, e, ref writeBack);
            }
            if (ovRes.MissingArgs > 0)
            {
                for (int i = ovRes.FixedArgs; i < ovRes.FixedArgs + ovRes.MissingArgs; i++)
                {
                    var conv = ovRes.Conversions[i];
                    var a    = new Arg(LiteralExpr.Bound(((ConversionSymbolToConstant)conv).Constant));
                    Convert(ref a.Expr, FindType(parameters[i].ParameterType), BindOptions.Default);
                    args.Args.Add(a);
                }
            }
            else if (ovRes.Parameters.HasParamArray)
            {
                var  varArgs    = new List <Expr>(ovRes.VarArgs);
                var  varArgType = FindType(parameters[ovRes.FixedArgs].ParameterType.GetElementType());
                bool hasRefArgs = false;
                for (int i = ovRes.FixedArgs; i < ovRes.FixedArgs + ovRes.VarArgs; i++)
                {
                    var conv = ovRes.Conversions[i];
                    var e    = args.Args[i].Expr;
                    Convert(ref e, varArgType, conv);
                    varArgs.Add(e);
                    if (args.Args[i].RefKind != RefKind.None)
                    {
                        hasRefArgs = true;
                    }
                }
                var varArg = new Arg(LiteralArray.Bound(varArgs, varArgType));
                if (hasRefArgs)
                {
                    var conv = ConversionSymbol.Create(ConversionSymbol.Create(ConversionKind.Identity), new ConversionToTemp(varArg.Expr.Datatype));
                    Convert(ref varArg.Expr, varArg.Expr.Datatype, conv);
                    for (int i = ovRes.FixedArgs; i < ovRes.FixedArgs + ovRes.VarArgs; i++)
                    {
                        if (args.Args[i].RefKind != RefKind.None)
                        {
                            HandleVarArgWriteBack(conv, args.Args[i].Expr, i - ovRes.FixedArgs, ref writeBack);
                        }
                    }
                }
                while (args.Args.Count > ovRes.FixedArgs)
                {
                    args.Args.RemoveAt(args.Args.Count - 1);
                }
                args.Args.Add(varArg);
            }

            void HandleArgWriteBack(ConversionSymbol conv, Expr e, ref Expr wb)
            {
                if (conv.IsIndirectRefConversion())
                {
                    if (e.Symbol?.HasSetAccess == true || e is AutoVarExpr || e is AliasExpr)
                    {
                        // Handle writeBack
                        Expr t  = IdExpr.Bound(conv.IndirectRefConversionTempLocal());
                        var  wc = Conversion(t, e.Datatype, BindOptions.Default);
                        if (wc.Exists)
                        {
                            Convert(ref t, e.Datatype, wc);
                            SymbolExtensions.AddExpr(ref wb, AssignExpr.Bound(e, t, BindOptions.Default));
                        }
                    }
                }
            }

            void HandleVarArgWriteBack(ConversionSymbol conv, Expr e, int i, ref Expr wb)
            {
                if (e.Symbol?.HasSetAccess == true || e is AutoVarExpr || e is AliasExpr)
                {
                    // Handle writeBack
                    Expr t = IdExpr.Bound(conv.IndirectRefConversionTempLocal());
                    t = ArrayAccessExpr.Bound(t, ArgList.Bound(LiteralExpr.Bound(Constant.Create(i + 1))), this);
                    var wc = Conversion(t, e.Datatype, BindOptions.Default);
                    if (wc.Exists)
                    {
                        Convert(ref t, e.Datatype, wc);
                        SymbolExtensions.AddExpr(ref wb, AssignExpr.Bound(e, t, BindOptions.Default));
                    }
                }
            }
        }