示例#1
0
        public void TestUnused()
        {
            /*
             * def kju() : Unit {
             *  struct X {};
             * }
             */

            var dummyRange = new Core.Lexer.Range(new StringLocation(0), new StringLocation(0));

            var xDeclaration = new StructDeclaration(dummyRange, "X", new List <StructField>());
            var xType        = StructType.GetInstance(xDeclaration);

            var kjuInstructions = new List <Expression> {
                xDeclaration
            };

            var kjuDeclaration = new FunctionDeclaration(
                dummyRange,
                "kju",
                new ArrayType(UnitType.Instance),
                new List <VariableDeclaration>(),
                new InstructionBlock(dummyRange, kjuInstructions),
                false);

            var root = new Program(dummyRange, new List <StructDeclaration>(), new List <FunctionDeclaration> {
                kjuDeclaration
            });

            this.CheckAnswer(root, new HashSet <DataType>()
            {
                xType
            });
        }
示例#2
0
            private void PopBlock()
            {
                var ids = this.variableBlocks.Pop();

                foreach (var id in ids)
                {
                    this.variables[id].Pop();
                }

                var funs = this.functionBlocks.Pop();

                foreach (var fun in funs)
                {
                    this.functions[fun.Key].Pop();
                }

                var structs = this.structBlocks.Pop();

                foreach (var structName in structs)
                {
                    this.structs[structName].Pop();
                    if (this.structs[structName].Count > 0)
                    {
                        var structDecl = this.structs[structName].Peek();
                        this.dataTypes[structName] = StructType.GetInstance(structDecl);
                    }
                    else
                    {
                        this.dataTypes.Remove(structName);
                    }
                }
            }
示例#3
0
        public void TestStructFunctionParameters()
        {
            var aDecl = new StructDeclaration(
                null,
                "A",
                new List <StructField>());

            var aParam = new VariableDeclaration(
                null,
                new UnresolvedType("A", null),
                "a",
                null);
            var f = new FunctionDeclaration(
                null,
                "f",
                new UnresolvedType("A", null),
                new List <VariableDeclaration>()
            {
                aParam
            },
                new InstructionBlock(
                    null,
                    new List <Expression>()
            {
                new FunctionCall(
                    null,
                    "f",
                    new List <Expression>()
                {
                    aParam
                }),
                new ReturnStatement(
                    null,
                    new Variable(
                        null,
                        "a")),
            }),
                false);

            var program = new Program(
                null,
                new List <StructDeclaration>()
            {
                aDecl
            },
                new List <FunctionDeclaration>()
            {
                f
            });

            this.nameResolver.Run(program, null);

            Assert.AreEqual(StructType.GetInstance(aDecl), f.ReturnType);
            Assert.AreEqual(StructType.GetInstance(aDecl), aParam.VariableType);
        }
示例#4
0
        public void TestStruct()
        {
            var x = new VariableDeclaration(
                null,
                new UnresolvedType("A", null),
                "x",
                null);
            var kju = new FunctionDeclaration(
                null,
                "kju",
                UnitType.Instance,
                new List <VariableDeclaration>()
            {
            },
                new InstructionBlock(
                    null,
                    new List <Expression>()
            {
                x,
            }),
                false);
            var globalADecl = new StructDeclaration(
                null,
                "A",
                new List <StructField>()
            {
                new StructField(null, "a", new UnresolvedType("A", null))
            });

            var program = new Program(
                null,
                new List <StructDeclaration>()
            {
                globalADecl
            },
                new List <FunctionDeclaration>()
            {
                kju
            });

            this.nameResolver.Run(program, null);

            Assert.AreEqual(StructType.GetInstance(globalADecl), x.VariableType);
            Assert.AreEqual(StructType.GetInstance(globalADecl), globalADecl.Fields[0].Type);
        }
示例#5
0
            private void ProcessProgram(Program program, IDiagnostics diagnostics)
            {
                this.functionBlocks.Push(new Dictionary <string, List <FunctionDeclaration> >());
                this.variableBlocks.Push(new HashSet <string>());
                this.structBlocks.Push(new HashSet <string>());

                foreach (var fun in program.Functions)
                {
                    var id = fun.Identifier;

                    if (!this.functions.ContainsKey(id))
                    {
                        this.functions.Add(id, new Stack <List <FunctionDeclaration> >());
                    }

                    this.AddToPeek(id, fun);
                }

                foreach (var structDecl in program.Structs)
                {
                    if (this.structs.ContainsKey(structDecl.Name))
                    {
                        var diagnostic = new Diagnostic(
                            DiagnosticStatus.Error,
                            MultipleDeclarationsDiagnostic,
                            $"Multiple declarations of struct {structDecl.Name}",
                            new List <Range> {
                            structDecl.InputRange
                        });
                        diagnostics.Add(diagnostic);
                        this.exceptions.Add(new NameResolverInternalException($"Multiple declarations struct {structDecl.Name}"));
                    }

                    this.dataTypes[structDecl.Name] = StructType.GetInstance(structDecl);
                    this.structs[structDecl.Name]   = new Stack <StructDeclaration>();
                    this.structs[structDecl.Name].Push(structDecl);
                    this.structBlocks.Peek().Add(structDecl.Name);
                }

                this.functionBlocks.Push(new Dictionary <string, List <FunctionDeclaration> >());
                this.variableBlocks.Push(new HashSet <string>());
                this.structBlocks.Push(new HashSet <string>());
            }
示例#6
0
        public void TestStructAlloc()
        {
            var aDecl = new StructDeclaration(
                null,
                "A",
                new List <StructField>());
            var aAlloc = new StructAlloc(
                null,
                new UnresolvedType("A", null));
            var kju = new FunctionDeclaration(
                null,
                "kju",
                UnitType.Instance,
                new List <VariableDeclaration>(),
                new InstructionBlock(
                    null,
                    new List <Expression>()
            {
                aAlloc
            }),
                false);

            var program = new Program(
                null,
                new List <StructDeclaration>()
            {
                aDecl
            },
                new List <FunctionDeclaration>()
            {
                kju
            });

            this.nameResolver.Run(program, null);

            Assert.AreEqual(StructType.GetInstance(aDecl), aAlloc.AllocType);
        }
示例#7
0
        private void CollectTypes(Node node, HashSet <DataType> dataTypes)
        {
            foreach (var child in node.Children())
            {
                this.CollectTypes(child, dataTypes);
            }

            switch (node)
            {
            case FunctionDeclaration functionDeclaration:
                if (functionDeclaration.Function?.ClosureType != null)     // only to make testing easier
                {
                    this.AddTypeWithSubtypes(functionDeclaration.Function.ClosureType, dataTypes);
                }
                break;

            default:
                break;
            }

            if (node is Expression)
            {
                this.AddTypeWithSubtypes(((Expression)node).Type, dataTypes);

                switch (node)
                {
                case StructDeclaration structDeclaration:
                    this.AddTypeWithSubtypes(StructType.GetInstance(structDeclaration), dataTypes);
                    break;

                case VariableDeclaration variableDeclaration:
                    this.AddTypeWithSubtypes(variableDeclaration.VariableType, dataTypes);
                    break;
                }
            }
        }
示例#8
0
            private void ProcessStructDeclaration(StructDeclaration structDeclaration, IDiagnostics diagnostics)
            {
                string name = structDeclaration.Name;

                if (this.structBlocks.Peek().Contains(name))
                {
                    var diagnostic = new Diagnostic(
                        DiagnosticStatus.Error,
                        MultipleDeclarationsDiagnostic,
                        $"Multiple declarations of struct {name}",
                        new List <Range> {
                        structDeclaration.InputRange
                    });
                    diagnostics.Add(diagnostic);
                    this.exceptions.Add(new NameResolverInternalException($"Multiple declarations struct {name}"));
                }

                if (this.buildInTypes.Contains(name))
                {
                    var diagnostic = new Diagnostic(
                        DiagnosticStatus.Error,
                        TypeIdentifierErrorDiagnosticsType,
                        $"Cannot use builtin type name {name}",
                        new List <Range> {
                        structDeclaration.InputRange
                    });
                    diagnostics.Add(diagnostic);
                    this.exceptions.Add(new NameResolverInternalException($"Cannot use builtin type name {name}"));
                }

                if (!this.structs.ContainsKey(name))
                {
                    this.structs.Add(name, new Stack <StructDeclaration>());
                }

                this.structs[name].Push(structDeclaration);
                this.structBlocks.Peek().Add(name);
                this.dataTypes[name] = StructType.GetInstance(structDeclaration);

                var fieldNames = new HashSet <string>();

                foreach (var field in structDeclaration.Fields)
                {
                    var fieldName = field.Name;
                    if (fieldNames.Contains(fieldName))
                    {
                        var diagnostic = new Diagnostic(
                            DiagnosticStatus.Error,
                            MultipleDeclarationsDiagnostic,
                            $"Multiple declarations of field: {fieldName} in struct: {name}",
                            new List <Range> {
                            structDeclaration.InputRange
                        });
                        diagnostics.Add(diagnostic);
                        this.exceptions.Add(new NameResolverInternalException($"Multiple field declarations struct {name}"));
                    }

                    fieldNames.Add(fieldName);
                }

                foreach (var field in structDeclaration.Fields)
                {
                    field.Type = this.ResolveDataType(field.Type, diagnostics);
                }
            }
示例#9
0
            private IEnumerable <Clause> GenerateClauses(Expression node)
            {
                switch (node)
                {
                case NullLiteral _:
                    break;

                case InstructionBlock _:
                case FunctionDeclaration _:
                case StructDeclaration _:
                case BreakStatement _:
                case ContinueStatement _:
                    yield return(this.EqualityClause(node, UnitType.Instance));

                    break;

                case VariableDeclaration decl:
                    if (decl.Value != null)
                    {
                        yield return(this.EqualityClause(decl.Value, decl.VariableType));
                    }

                    yield return(this.EqualityClause(node, UnitType.Instance));

                    break;

                case WhileStatement whileNode:
                    yield return(this.EqualityClause(whileNode.Condition, BoolType.Instance));

                    yield return(this.EqualityClause(node, UnitType.Instance));

                    break;

                case IfStatement ifNode:
                    yield return(this.EqualityClause(ifNode.Condition, BoolType.Instance));

                    yield return(this.EqualityClause(node, UnitType.Instance));

                    break;

                case FunctionCall funCall:
                {
                    Clause clause = this.OverloadsClause(funCall);
                    this.callOptions[funCall] = clause;
                    yield return(clause);

                    break;
                }

                case ReturnStatement returnNode:
                    yield return(returnNode.Value == null
                            ? this.EqualityClause(this.returnType.Peek(), UnitType.Instance, returnNode)
                            : this.EqualityClause(returnNode.Value, this.returnType.Peek()));

                    yield return(this.EqualityClause(returnNode, returnNode.Value?.Type ?? UnitType.Instance));

                    break;

                case Variable variable:
                    yield return(this.EqualityClause(variable, variable.Declaration.VariableType));

                    break;

                case BoolLiteral boolNode:
                    yield return(this.EqualityClause(boolNode, BoolType.Instance));

                    break;

                case IntegerLiteral integerNode:
                    yield return(this.EqualityClause(integerNode, IntType.Instance));

                    break;

                case UnitLiteral unitNode:
                    yield return(this.EqualityClause(unitNode, UnitType.Instance));

                    break;

                case Assignment assignment:
                    yield return(this.EqualityClause(assignment.Value, assignment.Lhs.Declaration.VariableType));

                    yield return(this.EqualityClause(assignment, assignment.Value.Type));

                    break;

                case CompoundAssignment assignment:
                    yield return(this.EqualityClause(assignment.Lhs.Declaration.VariableType, IntType.Instance, assignment.Lhs));

                    yield return(this.EqualityClause(assignment.Value, IntType.Instance));

                    yield return(this.EqualityClause(assignment, IntType.Instance));

                    break;

                case ArithmeticOperation operationNode:
                    yield return(this.EqualityClause(operationNode.LeftValue, IntType.Instance));

                    yield return(this.EqualityClause(operationNode.RightValue, IntType.Instance));

                    yield return(this.EqualityClause(operationNode, IntType.Instance));

                    break;

                case Comparison cmp:
                {
                    switch (cmp.OperationType)
                    {
                    case ComparisonType.Equal:
                    case ComparisonType.NotEqual:
                        yield return(this.EqualityClause(cmp.LeftValue.Type, cmp.RightValue.Type, cmp));

                        break;

                    case ComparisonType.Less:
                    case ComparisonType.LessOrEqual:
                    case ComparisonType.Greater:
                    case ComparisonType.GreaterOrEqual:
                        yield return(this.EqualityClause(cmp.LeftValue, IntType.Instance));

                        yield return(this.EqualityClause(cmp.RightValue, IntType.Instance));

                        break;
                    }

                    yield return(this.EqualityClause(cmp, BoolType.Instance));

                    break;
                }

                case UnaryOperation op:
                {
                    IHerbrandObject type = UnaryOperationToType[op.UnaryOperationType];
                    yield return(this.EqualityClause(op.Value, type));

                    yield return(this.EqualityClause(op, type));

                    break;
                }

                case LogicalBinaryOperation op:
                    yield return(this.EqualityClause(op.LeftValue, BoolType.Instance));

                    yield return(this.EqualityClause(op.RightValue, BoolType.Instance));

                    yield return(this.EqualityClause(op, BoolType.Instance));

                    break;

                case ArrayAlloc alloc:
                    yield return(this.EqualityClause(alloc.Size, IntType.Instance));

                    yield return(this.EqualityClause(alloc, new ArrayType(alloc.ElementType)));

                    break;

                case ArrayAccess access:
                    yield return(this.EqualityClause(access.Index, IntType.Instance));

                    yield return(this.EqualityClause(access.Lhs, new ArrayType(access.Type)));

                    break;

                case ComplexAssignment assignment:
                    yield return(this.EqualityClause(assignment.Lhs, assignment.Value.Type));

                    yield return(this.EqualityClause(assignment, assignment.Value.Type));

                    break;

                case ComplexCompoundAssignment assignment:
                    yield return(this.EqualityClause(assignment.Lhs, IntType.Instance));

                    yield return(this.EqualityClause(assignment.Value, IntType.Instance));

                    yield return(this.EqualityClause(assignment, IntType.Instance));

                    break;

                case FieldAccess access:
                    yield return(this.StructCandidatesClause(access));

                    break;

                case StructAlloc alloc:
                    yield return(this.EqualityClause(alloc, StructType.GetInstance(alloc.Declaration)));

                    break;

                case Application app:
                    yield return(this.EqualityClause(
                                     app.Function,
                                     new FunType(app.Arguments.Select(arg => arg.Type), app.Type)));

                    break;

                case UnApplication unapp:
                {
                    Clause clause = new Clause(
                        unapp.Candidates
                        .Select(decl => new Alternative {
                            (unapp.Type, new FunType(decl))
                        })
                        .ToList(), unapp.InputRange);
                    this.unappOptions[unapp] = clause;
                    yield return(clause);

                    break;
                }
示例#10
0
        public void TestStructShadowing()
        {
            var innerADecl = new StructDeclaration(
                null,
                "A",
                new List <StructField>()
            {
                new StructField(null, "b", IntType.Instance)
            });
            var globalADecl = new StructDeclaration(
                null,
                "A",
                new List <StructField>()
            {
                new StructField(null, "a", IntType.Instance)
            });

            var x1 = new VariableDeclaration(
                null,
                new UnresolvedType("A", null),
                "x1",
                null);
            var x2 = new VariableDeclaration(
                null,
                new UnresolvedType("A", null),
                "x2",
                null);
            var y = new VariableDeclaration(
                null,
                new UnresolvedType("A", null),
                "y",
                null);

            var kju = new FunctionDeclaration(
                null,
                "kju",
                UnitType.Instance,
                new List <VariableDeclaration>()
            {
            },
                new InstructionBlock(
                    null,
                    new List <Expression>()
            {
                x1,
                new InstructionBlock(null, new List <Expression>()
                {
                    innerADecl,
                    y,
                }),
                x2,
            }),
                false);

            var program = new Program(
                null,
                new List <StructDeclaration>()
            {
                globalADecl
            },
                new List <FunctionDeclaration>()
            {
                kju
            });

            this.nameResolver.Run(program, null);

            Assert.AreEqual(StructType.GetInstance(globalADecl), x1.VariableType);
            Assert.AreEqual(StructType.GetInstance(globalADecl), x2.VariableType);
            Assert.AreEqual(StructType.GetInstance(innerADecl), y.VariableType);
        }
示例#11
0
        public void TestComplex()
        {
            /*
             * def kju() : Unit {
             *  struct P {
             *      x : [Int];
             *  };
             *
             *  struct S {
             *    x : Int;
             *    y : P;
             *  };
             *
             *  var s : [S] = new(S, 10);
             *  var arr : [[Bool]] = new([Bool], 20);
             * }
             */

            var dummyRange = new Core.Lexer.Range(new StringLocation(0), new StringLocation(0));

            var pFields = new List <StructField>()
            {
                new StructField(dummyRange, "x", new ArrayType(IntType.Instance))
            };

            var pDeclaration = new StructDeclaration(dummyRange, "P", pFields);
            var pType        = StructType.GetInstance(pDeclaration);

            var sFields = new List <StructField>()
            {
                new StructField(dummyRange, "x", IntType.Instance),
                new StructField(dummyRange, "y", pType)
            };

            var sDeclaration = new StructDeclaration(dummyRange, "S", sFields);
            var sType        = StructType.GetInstance(sDeclaration);

            var sAlloc = new ArrayAlloc(
                dummyRange, sType, new IntegerLiteral(dummyRange, 10));
            var sVarDeclaration = new VariableDeclaration(
                dummyRange,
                new ArrayType(sType),
                "s",
                sAlloc);

            var arrAlloc = new ArrayAlloc(
                dummyRange, new ArrayType(BoolType.Instance), new IntegerLiteral(dummyRange, 20));
            var arrVarDeclaration = new VariableDeclaration(
                dummyRange,
                new ArrayType(new ArrayType(BoolType.Instance)),
                "arr",
                arrAlloc);

            var kjuInstructions = new List <Expression> {
                pDeclaration,
                sDeclaration,
                sVarDeclaration,
                arrVarDeclaration
            };

            var kjuDeclaration = new FunctionDeclaration(
                dummyRange,
                "kju",
                new ArrayType(UnitType.Instance),
                new List <VariableDeclaration>(),
                new InstructionBlock(dummyRange, kjuInstructions),
                false);

            var root = new Program(dummyRange, new List <StructDeclaration>(), new List <FunctionDeclaration> {
                kjuDeclaration
            });

            var expectedTypes = new HashSet <DataType>()
            {
                pType,
                sType,
                new ArrayType(BoolType.Instance),
                new ArrayType(IntType.Instance),
                new ArrayType(sType),
                new ArrayType(new ArrayType(BoolType.Instance))
            };

            this.CheckAnswer(root, expectedTypes);
        }