Пример #1
0
        public static void GenerateCode(OperatorCall call, GeneratorContext builder)
        {
            if (call.LeftInput != null)
            {
                builder.AddCode(call.LeftInput);
            }
            if (call.RightInput != null)
            {
                builder.AddCode(call.RightInput);
            }

            builder.AddOp(new CallBuiltIn(call.BuiltInFunctionHint), call.OperatorToken);
        }
Пример #2
0
 private Color GetColor(SprakExpression item)
 {
     return(item switch
     {
         Block block => GetColor(block.Header),
         Command _ => Colors.Blue,
         FunctionCall _ => Colors.Orange,
         FunctionHeader _ => Colors.Blue,
         IfHeader _ => Colors.DarkRed,
         LiteralArrayGet _ => Colors.Yellow,
         LiteralGet _ => Colors.Yellow,
         LoopHeader _ => Colors.Red,
         MainHeader _ => Colors.Orange,
         OperatorCall _ => Colors.Green,
         Return _ => Colors.Blue,
         VariableAssignment _ => Colors.Orange,
         VariableReference _ => Colors.Yellow,
         _ => Colors.Black
     });
Пример #3
0
        private void ResolveCallAndTypeHint(OperatorCall call, CompilationEnvironment env)
        {
            if (!Operator.TryParse(out Operator op, text: call.OperatorText))
            {
                env.Messages.AtToken(call.OperatorToken,
                                     Messages.UnrecognizedOperator, call.OperatorText);
                return;
            }

            if (op.IsAssignment)
            {
                env.Messages.AtToken(call.OperatorToken,
                                     Messages.IncorrectUseOfAssignment, op.Text);
                return;
            }

            call.TypeHint = null;

            if (call.LeftInput != null && call.LeftInput.TypeHint == null)
            {
                return;
            }

            if (call.RightInput != null && call.RightInput.TypeHint == null)
            {
                return;
            }

            SprakType  left  = call.LeftInput?.TypeHint;
            SprakType  right = call.RightInput?.TypeHint;
            InputSides inputs;

            if (left != null && right != null)
            {
                inputs = InputSides.Both;
            }

            else if (left != null)
            {
                inputs = InputSides.Left;
            }

            else
            {
                inputs = InputSides.Right;
            }

            OperatorTypeSignature signature
                = new OperatorTypeSignature(left, right, inputs);

            SignatureLookupResult lookupResult;

            lookupResult = env.SignatureLookup
                           .TryFindMatch(op.Name, signature);

            if (lookupResult.Success)
            {
                call.BuiltInFunctionHint = lookupResult.BuiltInFunction;
                call.TypeHint            = lookupResult.FunctionInfo?.ReturnType;
            }
            else
            {
                string operation = $"({call.LeftInput?.TypeHint?.Text})"
                                   + $" {call.OperatorToken.Content}"
                                   + $" ({call.RightInput?.TypeHint?.Text})";

                env.Messages.AtToken(call.OperatorToken,
                                     Messages.UnresolvedOperation, operation);
            }
        }
Пример #4
0
        public static Expression Create(MatchIterator iterator)
        {
            LinkedList <object> items = new LinkedList <object>();

            iterator.AssertNext();

            // postfix unary operators are not supported here
            // (Like i--, etc)
            // I don't think they are really needed for sprak, and defaulting
            // to assuming prefix simplifies things.

            while (true)
            {
                items.AddLast(GetValue(iterator));

                if (iterator.AtEnd())
                {
                    break;
                }

                iterator.AssertTokenType(TokenType.Operator, out Token op);
                items.AddLast(op);

                if (iterator.AtEnd())
                {
                    break;
                }
            }

            void ParseOperatorToken(LinkedListNode <object> opNode)
            {
                Token token = (Token)opNode.Value;
                LinkedListNode <object> leftNode  = opNode.Previous;
                LinkedListNode <object> rightNode = opNode.Next;

                Expression   left   = (Expression)leftNode.Value;
                Expression   right  = (Expression)rightNode?.Value;
                OperatorCall result = new OperatorCall(token, left, right);

                items.AddBefore(leftNode, result);

                items.Remove(leftNode);
                items.Remove(opNode);

                if (rightNode != null)
                {
                    items.Remove(rightNode);
                }
            }

            LinkedListNode <object> current, next;

            foreach (Operator[] group in Operator.OperatorPrecedenceGroups)
            {
                current = items.First.Next;

                while (current != null)
                {
                    next = current.Next?.Next;

                    Token token = (Token)current.Value;
                    if (Operator.TryParse(out Operator op, text:token.Content))
                    {
                        if (group.Contains(op))
                        {
                            ParseOperatorToken(current);
                        }
                    }

                    current = next;
                }
            }

            current = items.First.Next;
            while (current != null)
            {
                ParseOperatorToken(current);
                current = current.Next?.Next;
            }

            if (items.First.Next != null)
            {
                throw new Exception("Unable to parse all operators");
            }

            return((Expression)items.First.Value);
        }