Example #1
0
        private void ResolveExprLoop(ref int segment, sema.Code.Lvalue destination, syn.Node.Loop node)
        {
            var bodySegment    = this.code.CreateSegment();
            var bodySegmentEnd = bodySegment;

            var afterSegment = this.code.CreateSegment();

            segment = afterSegment;

            this.code.SetTerminator(segment, new sema.Code.Terminator.Goto {
                segmentIndex = bodySegment
            });

            this.breakSegments.Push(afterSegment);
            this.continueSegments.Push(bodySegment);

            this.ResolveExpr(ref bodySegmentEnd, new sema.Code.Lvalue.Discard {
                span = node.block.span
            }, node.block);
            this.code.SetTerminator(bodySegmentEnd, new sema.Code.Terminator.Goto {
                segmentIndex = bodySegment
            });

            this.breakSegments.Pop();
            this.continueSegments.Pop();

            this.AddVoidInstruction(segment, destination, node.span);
        }
Example #2
0
        private void ResolveExprLet(ref int segment, sema.Code.Lvalue destination, syn.Node.Let node)
        {
            var registerIndex = this.CreateRegister();
            var register      = this.code.registers[registerIndex];

            register.spanDef     = node.span;
            register.spanDefName = node.identifier.span;
            register.name        = (node.identifier as syn.Node.Identifier).token.excerpt;

            if (node.type != null)
            {
                register.type = TypeResolver.Resolve(this.ctx, this.reporter, node.type);
            }
            else
            {
                register.type = new sema.Type.Placeholder();
            }

            if (node.expr != null)
            {
                var assignDestination = new sema.Code.Lvalue.Register
                {
                    span  = node.identifier.span,
                    index = registerIndex
                };

                this.ResolveExpr(ref segment, assignDestination, node.expr);
            }

            this.AddVoidInstruction(segment, destination, node.span);
        }
Example #3
0
        private void ResolveExprBlock(ref int segment, sema.Code.Lvalue destination, syn.Node.Block node)
        {
            if (node.exprs.Count == 0)
            {
                this.AddVoidInstruction(segment, destination, node.span);
                return;
            }

            var scopeIndexBefore = this.registersInScope.Count;

            for (var i = 0; i < node.exprs.Count; i++)
            {
                var exprDestination = destination;
                if (i < node.exprs.Count - 1)
                {
                    exprDestination = new sema.Code.Lvalue.Discard();
                }

                this.ResolveExpr(ref segment, exprDestination, node.exprs[i]);
            }

            for (var i = scopeIndexBefore; i < this.registersInScope.Count; i++)
            {
                this.registersInScope[i] = false;
            }
        }
Example #4
0
 private void ResolveExprBool(ref int segment, sema.Code.Lvalue destination, syn.Node.LiteralBool node)
 {
     this.code.AddInstruction(segment, new sema.Code.Instruction.CopyLiteralBool
     {
         span        = node.span,
         destination = destination,
         value       = node.value
     });
 }
Example #5
0
 private void ResolveExprNumber(ref int segment, sema.Code.Lvalue destination, syn.Node.Number node)
 {
     this.code.AddInstruction(segment, new sema.Code.Instruction.CopyLiteralNumber
     {
         span        = node.span,
         destination = destination,
         excerpt     = node.token.excerpt
     });
 }
Example #6
0
 private void ResolveExprName(ref int segment, sema.Code.Lvalue destination, syn.Node.Identifier node)
 {
     this.code.AddInstruction(segment, new sema.Code.Instruction.CopyLvalue
     {
         span        = node.span,
         destination = destination,
         source      = this.ResolveLvalue(ref segment, node)
     });
 }
Example #7
0
        private void ResolveExprIf(ref int segment, sema.Code.Lvalue destination, syn.Node.If node)
        {
            var conditionRegIndex = this.ResolveIntoNewRegister(
                ref segment, node.condition, new sema.Type.Structure {
                def = ctx.primitiveBool
            });

            var conditionLvalue = new sema.Code.Lvalue.Register {
                index = conditionRegIndex, span = node.condition.span
            };

            this.ResolveExpr(ref segment, conditionLvalue, node.condition);

            var branch = new sema.Code.Terminator.Branch {
                conditionRegisterIndex = conditionRegIndex
            };

            this.code.SetTerminator(segment, branch);

            var trueSegment = this.code.CreateSegment();

            branch.trueSegmentIndex = trueSegment;
            this.ResolveExpr(ref trueSegment, new sema.Code.Lvalue.Discard {
                span = node.trueBlock.span
            }, node.trueBlock);

            if (node.falseBlock != null)
            {
                var falseSegment = this.code.CreateSegment();
                branch.falseSegmentIndex = falseSegment;
                this.ResolveExpr(ref falseSegment, new sema.Code.Lvalue.Discard {
                    span = node.falseBlock.span
                }, node.falseBlock);
                var afterSegment = this.code.CreateSegment();
                this.code.SetTerminator(trueSegment, new sema.Code.Terminator.Goto {
                    segmentIndex = afterSegment
                });
                this.code.SetTerminator(falseSegment, new sema.Code.Terminator.Goto {
                    segmentIndex = afterSegment
                });
                segment = afterSegment;
            }
            else
            {
                var afterSegment = this.code.CreateSegment();
                branch.falseSegmentIndex = afterSegment;
                this.code.SetTerminator(trueSegment, new sema.Code.Terminator.Goto {
                    segmentIndex = afterSegment
                });
                segment = afterSegment;
            }

            this.AddVoidInstruction(segment, destination, node.span);
        }
Example #8
0
        private void AddVoidInstruction(int segment, sema.Code.Lvalue destination, diagn.Span span)
        {
            if (destination is sema.Code.Lvalue.Discard)
            {
                return;
            }

            this.code.AddInstruction(segment, new sema.Code.Instruction.CopyLiteralTuple
            {
                destination = destination,
                span        = span
            });
        }
Example #9
0
 private void ResolveExprBinaryOp(ref int segment, sema.Code.Lvalue destination, syn.Node.BinaryOperation node)
 {
     if (node.op == syn.Node.BinaryOperator.Assign)
     {
         var assignDestination = this.ResolveLvalue(ref segment, node.lhs);
         this.ResolveExpr(ref segment, assignDestination, node.rhs);
         this.AddVoidInstruction(segment, destination, node.span);
     }
     else
     {
         this.reporter.InternalError("unimplemented", new diagn.Caret(node.span));
     }
 }
Example #10
0
        private void ResolveExprWhile(ref int segment, sema.Code.Lvalue destination, syn.Node.While node)
        {
            var conditionSegment    = this.code.CreateSegment();
            var conditionSegmentEnd = conditionSegment;

            this.code.SetTerminator(segment, new sema.Code.Terminator.Goto {
                segmentIndex = conditionSegment
            });

            var conditionRegIndex = this.ResolveIntoNewRegister(
                ref conditionSegmentEnd, node.condition, new sema.Type.Structure {
                def = ctx.primitiveBool
            });

            var conditionLvalue = new sema.Code.Lvalue.Register {
                index = conditionRegIndex, span = node.condition.span
            };

            this.ResolveExpr(ref conditionSegmentEnd, conditionLvalue, node.condition);

            var branch = new sema.Code.Terminator.Branch {
                conditionRegisterIndex = conditionRegIndex
            };

            this.code.SetTerminator(conditionSegmentEnd, branch);

            var bodySegment  = this.code.CreateSegment();
            var afterSegment = this.code.CreateSegment();

            branch.trueSegmentIndex = bodySegment;

            this.breakSegments.Push(afterSegment);
            this.continueSegments.Push(conditionSegment);

            this.ResolveExpr(ref bodySegment, new sema.Code.Lvalue.Discard {
                span = node.block.span
            }, node.block);
            this.code.SetTerminator(bodySegment, new sema.Code.Terminator.Goto {
                segmentIndex = conditionSegment
            });

            this.breakSegments.Pop();
            this.continueSegments.Pop();

            branch.falseSegmentIndex = afterSegment;
            segment = afterSegment;

            this.AddVoidInstruction(segment, destination, node.span);
        }
Example #11
0
        private void ResolveExprTuple(ref int segment, sema.Code.Lvalue destination, syn.Node.LiteralTuple node)
        {
            var elems = new List <int>();

            foreach (var elem in node.elems)
            {
                elems.Add(this.ResolveIntoNewRegister(ref segment, elem));
            }

            this.code.AddInstruction(segment, new sema.Code.Instruction.CopyLiteralTuple
            {
                span        = node.span,
                destination = destination,
                sources     = elems
            });
        }
Example #12
0
        private void ResolveExprContinue(ref int segment, sema.Code.Lvalue destination, syn.Node.Continue node)
        {
            if (this.continueSegments.Count == 0)
            {
                this.reporter.Error("`continue` not inside a loop", new diagn.Caret(node.span));
                this.code.SetTerminator(segment, new sema.Code.Terminator.Error {
                });
            }
            else
            {
                this.code.SetTerminator(segment, new sema.Code.Terminator.Goto {
                    segmentIndex = this.continueSegments.Peek()
                });

                segment = this.code.CreateSegment();
                this.AddVoidInstruction(segment, destination, node.span);
            }
        }
Example #13
0
        private void ResolveExprReturn(ref int segment, sema.Code.Lvalue destination, syn.Node.Return node)
        {
            if (node.expr != null)
            {
                this.ResolveExpr(ref segment, new sema.Code.Lvalue.Register {
                    index = 0
                }, node.expr);
            }
            else
            {
                this.AddVoidInstruction(segment, new sema.Code.Lvalue.Register {
                    index = 0
                }, node.span);
            }

            this.code.SetTerminator(segment, new sema.Code.Terminator.Return {
            });

            segment = this.code.CreateSegment();
            this.AddVoidInstruction(segment, destination, node.span);
        }
Example #14
0
        private void ResolveExpr(ref int segment, sema.Code.Lvalue destination, syn.Node node)
        {
            var nodeParen      = node as syn.Node.Parenthesized;
            var nodeBlock      = node as syn.Node.Block;
            var nodeLet        = node as syn.Node.Let;
            var nodeIf         = node as syn.Node.If;
            var nodeWhile      = node as syn.Node.While;
            var nodeLoop       = node as syn.Node.Loop;
            var nodeBreak      = node as syn.Node.Break;
            var nodeContinue   = node as syn.Node.Continue;
            var nodeReturn     = node as syn.Node.Return;
            var nodeIdentifier = node as syn.Node.Identifier;
            var nodeNumber     = node as syn.Node.Number;
            var nodeBool       = node as syn.Node.LiteralBool;
            var nodeTuple      = node as syn.Node.LiteralTuple;
            var nodeBinaryOp   = node as syn.Node.BinaryOperation;

            if (nodeParen != null)
            {
                this.ResolveExpr(ref segment, destination, nodeParen.inner);
            }

            else if (nodeBlock != null)
            {
                this.ResolveExprBlock(ref segment, destination, nodeBlock);
            }

            else if (nodeLet != null)
            {
                this.ResolveExprLet(ref segment, destination, nodeLet);
            }

            else if (nodeIf != null)
            {
                this.ResolveExprIf(ref segment, destination, nodeIf);
            }

            else if (nodeWhile != null)
            {
                this.ResolveExprWhile(ref segment, destination, nodeWhile);
            }

            else if (nodeLoop != null)
            {
                this.ResolveExprLoop(ref segment, destination, nodeLoop);
            }

            else if (nodeBreak != null)
            {
                this.ResolveExprBreak(ref segment, destination, nodeBreak);
            }

            else if (nodeContinue != null)
            {
                this.ResolveExprContinue(ref segment, destination, nodeContinue);
            }

            else if (nodeReturn != null)
            {
                this.ResolveExprReturn(ref segment, destination, nodeReturn);
            }

            else if (nodeIdentifier != null)
            {
                this.ResolveExprName(ref segment, destination, nodeIdentifier);
            }

            else if (nodeNumber != null)
            {
                this.ResolveExprNumber(ref segment, destination, nodeNumber);
            }

            else if (nodeBool != null)
            {
                this.ResolveExprBool(ref segment, destination, nodeBool);
            }

            else if (nodeTuple != null)
            {
                this.ResolveExprTuple(ref segment, destination, nodeTuple);
            }

            else if (nodeBinaryOp != null)
            {
                this.ResolveExprBinaryOp(ref segment, destination, nodeBinaryOp);
            }

            else
            {
                this.reporter.InternalError("unimplemented", new diagn.Caret(node.span));
            }
        }