Example #1
0
        private void ResolveExprLet(Grammar.ASTNodeExprLet exprLet, ref int curSegment, Core.DataAccess output)
        {
            // Create a new storage location and name binding.
            var registerIndex = funct.CreateRegister(new Core.TypePlaceholder(), exprLet.mutable);
            var name          = NameResolver.Resolve(((Grammar.ASTNodeExprNameConcrete)exprLet.name).name);

            funct.CreateBinding(
                name,
                registerIndex,
                exprLet.name.GetSpan());

            localScopeLivenesses.Add(true);

            // Parse type annotation, if there is one.
            if (exprLet.type != null)
            {
                funct.registerTypes[registerIndex] =
                    TypeResolver.Resolve(session, exprLet.type, useDirectives, false);
            }

            // Parse init expression, if there is one.
            if (exprLet.initExpr != null)
            {
                ResolveExpr(exprLet.initExpr, ref curSegment,
                            Core.DataAccessRegister.ForRegister(exprLet.name.GetSpan(), registerIndex));
            }

            // Generate a void store.
            funct.AddInstruction(curSegment,
                                 Core.InstructionMoveLiteralTuple.Empty(exprLet.GetSpan(), output));
        }
Example #2
0
        private void ConvertStructDecl(Grammar.ASTNodeDeclStruct structNode, Core.Name curNamespace, List <Core.UseDirective> useDirectives)
        {
            var name = curNamespace.Concatenate(NameResolver.Resolve(structNode.name));

            if (!ValidateName(name, structNode.name.GetSpan()))
            {
                return;
            }

            var structIndex = this.session.CreateStruct(name, structNode);

            foreach (var structUseNode in structNode.useDirectives)
            {
                useDirectives.Add(UseDirectiveResolver.Resolve(structUseNode));
            }

            this.structWorkData.Add(new StructWorkData
            {
                name          = name,
                declNode      = structNode,
                declIndex     = structIndex,
                useDirectives = useDirectives.ToArray()
            });

            foreach (var structUseNode in structNode.useDirectives)
            {
                useDirectives.RemoveAt(useDirectives.Count - 1);
            }
        }
Example #3
0
        private void ConvertNamespaceDecl(Grammar.ASTNodeDeclNamespace namespaceNode, Core.Name curNamespace, List <Core.UseDirective> useDirectives)
        {
            var innerNamespace = curNamespace.Concatenate(NameResolver.ResolvePath(namespaceNode.path));

            for (var i = 0; i < namespaceNode.path.identifiers.Count; i++)
            {
                useDirectives.Add(new Core.UseDirectiveAll {
                    name = curNamespace.ConcatenateIdentifier(namespaceNode.path.identifiers[i].GetExcerpt())
                });
            }

            this.ConvertDeclGroup(namespaceNode.innerGroup, innerNamespace, useDirectives);

            for (var i = 0; i < namespaceNode.path.identifiers.Count; i++)
            {
                useDirectives.RemoveAt(useDirectives.Count - 1);
            }
        }
Example #4
0
        private void ConvertFunctDecl(Grammar.ASTNodeDeclFunct functNode, Core.Name curNamespace, List <Core.UseDirective> useDirectives)
        {
            var name = curNamespace.Concatenate(NameResolver.Resolve(functNode.name));

            if (!ValidateName(name, functNode.name.GetSpan()))
            {
                return;
            }

            var functIndex = this.session.CreateFunct(name);

            this.functWorkData.Add(new FunctWorkData
            {
                name          = name,
                declNode      = functNode,
                declIndex     = functIndex,
                useDirectives = useDirectives.ToArray()
            });
        }
Example #5
0
        public static Core.Type ResolveStruct(
            Core.Session session,
            Grammar.ASTNodeName nameNode,
            IList <Core.UseDirective> useDirectives,
            bool mustBeResolved)
        {
            var name = NameResolver.Resolve(nameNode);

            var foundDecls = session.GetDeclsWithUseDirectives(name, nameNode.path.isRooted, useDirectives);

            if (!session.ValidateSingleDecl(foundDecls, name, nameNode.GetSpan()))
            {
                return(new Core.TypeError());
            }

            if (!session.ValidateAsType(foundDecls[0], name, nameNode.GetSpan()))
            {
                return(new Core.TypeError());
            }

            return(Core.TypeStruct.Of(foundDecls[0].index));
        }
Example #6
0
        private void ResolveExprName(Grammar.ASTNodeExprName exprName, ref int curSegment, Core.DataAccess output)
        {
            var name = NameResolver.Resolve(((Grammar.ASTNodeExprNameConcrete)exprName).name);

            // Try to find a local with the same name.
            var bindingIndex = FindLocalBinding(name);

            if (bindingIndex >= 0)
            {
                funct.AddInstruction(curSegment,
                                     Core.InstructionMoveData.Of(
                                         exprName.GetSpan(),
                                         output,
                                         Core.DataAccessRegister.ForRegister(
                                             exprName.GetSpan(),
                                             funct.localBindings[bindingIndex].registerIndex)));
                return;
            }

            // Try to find a group of functs with the same name.
            var functList = session.GetDeclsWithUseDirectives(name, false, useDirectives);

            if (session.ValidateSingleDecl(functList, name, exprName.GetSpan()) &&
                session.ValidateAsFunct(functList[0], name, exprName.GetSpan()))
            {
                funct.AddInstruction(curSegment,
                                     Core.InstructionMoveLiteralFunct.With(exprName.GetSpan(), output, functList[0].index));
                return;
            }

            this.foundErrors = true;
            session.AddMessage(
                Diagnostics.MessageKind.Error,
                Diagnostics.MessageCode.Unknown,
                "unknown '" + name.GetString() + "'",
                exprName.GetSpan());
            throw new Core.CheckException();
        }
Example #7
0
        private Core.DataAccess ResolveDataAccess(Grammar.ASTNodeExpr expr, ref int curSegment, bool allowInnerExpr, bool mutInnerExpr)
        {
            while (true)
            {
                var exprParenthesized = expr as Grammar.ASTNodeExprParenthesized;
                if (exprParenthesized != null)
                {
                    expr = exprParenthesized.innerExpr;
                }
                else
                {
                    break;
                }
            }

            var exprConcreteName = expr as Grammar.ASTNodeExprNameConcrete;

            if (exprConcreteName != null)
            {
                var name         = NameResolver.Resolve(exprConcreteName.name);
                var bindingIndex = FindLocalBinding(name);

                if (bindingIndex >= 0)
                {
                    var localRegisterIndex = funct.localBindings[bindingIndex].registerIndex;
                    return(Core.DataAccessRegister.ForRegister(expr.GetSpan(), localRegisterIndex));
                }
                else
                {
                    this.foundErrors = true;
                    session.AddMessage(
                        Diagnostics.MessageKind.Error,
                        Diagnostics.MessageCode.Unknown,
                        "unknown '" + name.GetString() + "'",
                        expr.GetSpan());
                    return(null);
                }
            }

            var exprDereference = expr as Grammar.ASTNodeExprUnaryOp;

            if (exprDereference != null && exprDereference.oper == Grammar.ASTNodeExprUnaryOp.Operator.At)
            {
                var innerAccess = ResolveDataAccess(exprDereference.operand, ref curSegment, true, false);
                return(Core.DataAccessDereference.Of(exprDereference.GetSpan(), innerAccess));
            }

            var exprDotOp = expr as Grammar.ASTNodeExprBinaryOp;

            if (exprDotOp != null && exprDotOp.oper == Grammar.ASTNodeExprBinaryOp.Operator.Dot)
            {
                var baseAccess = ResolveDataAccess(exprDotOp.lhsOperand, ref curSegment, true, false);

                // Left-hand side expr type must be resolved for field access.
                FunctTypeInferencer.DoInference(this.session, this.funct);

                if (!TypeResolver.ValidateDataAccess(this.session, this.funct, baseAccess))
                {
                    this.foundErrors = true;
                    return(null);
                }

                var lhsType = TypeResolver.GetDataAccessType(this.session, this.funct, baseAccess);

                var lhsStruct = lhsType as Core.TypeStruct;
                if (lhsStruct != null && lhsType.IsResolved())
                {
                    var rhsFieldName = exprDotOp.rhsOperand as Grammar.ASTNodeExprNameConcrete;
                    if (rhsFieldName == null)
                    {
                        this.foundErrors = true;
                        session.AddMessage(
                            Diagnostics.MessageKind.Error,
                            Diagnostics.MessageCode.Expected,
                            "expected field name",
                            exprDotOp.rhsOperand.GetSpan());
                        return(null);
                    }

                    var name = NameResolver.Resolve(rhsFieldName.name);

                    int fieldIndex;
                    if (!this.session.GetStruct(lhsStruct.structIndex).fieldNames.FindByName(
                            name, out fieldIndex))
                    {
                        this.foundErrors = true;
                        session.AddMessage(
                            Diagnostics.MessageKind.Error,
                            Diagnostics.MessageCode.Unknown,
                            "unknown field '" + name.GetString() + "' in '" +
                            lhsType.GetString(this.session) + "'",
                            exprDotOp.rhsOperand.GetSpan(),
                            exprDotOp.lhsOperand.GetSpan());
                        return(null);
                    }

                    return(Core.DataAccessField.Of(exprDotOp.GetSpan(), baseAccess, fieldIndex));
                }

                var lhsTuple = lhsType as Core.TypeTuple;
                if (lhsTuple != null)
                {
                    var rhsFieldIndex = exprDotOp.rhsOperand as Grammar.ASTNodeExprLiteralInt;
                    if (rhsFieldIndex == null)
                    {
                        this.foundErrors = true;
                        session.AddMessage(
                            Diagnostics.MessageKind.Error,
                            Diagnostics.MessageCode.Expected,
                            "expected field index",
                            exprDotOp.rhsOperand.GetSpan());
                        return(null);
                    }

                    var fieldIndex = System.Convert.ToInt32(rhsFieldIndex.value);

                    if (fieldIndex < 0 || fieldIndex >= lhsTuple.elementTypes.Length)
                    {
                        this.foundErrors = true;
                        session.AddMessage(
                            Diagnostics.MessageKind.Error,
                            Diagnostics.MessageCode.Unknown,
                            "invalid field index for '" +
                            lhsType.GetString(this.session) + "'",
                            exprDotOp.rhsOperand.GetSpan(),
                            exprDotOp.lhsOperand.GetSpan());
                        return(null);
                    }

                    return(Core.DataAccessField.Of(exprDotOp.GetSpan(), baseAccess, fieldIndex));
                }

                if (!lhsType.IsError() && !lhsType.IsResolved())
                {
                    this.foundErrors = true;
                    session.AddMessage(
                        Diagnostics.MessageKind.Error,
                        Diagnostics.MessageCode.EarlyInferenceFailed,
                        "type must be known but inference up to this point failed",
                        exprDotOp.lhsOperand.GetSpan());
                    return(null);
                }

                this.foundErrors = true;
                session.AddMessage(
                    Diagnostics.MessageKind.Error,
                    Diagnostics.MessageCode.WrongFieldAccess,
                    "attempted field access on '" + lhsType.GetString(this.session) + "'",
                    exprDotOp.lhsOperand.GetSpan());
                return(null);
            }

            if (allowInnerExpr)
            {
                // Generate a new register for inner expression.
                var registerIndex = this.funct.CreateRegister(new Core.TypePlaceholder(), mutInnerExpr);
                var access        = Core.DataAccessRegister.ForRegister(expr.GetSpan(), registerIndex);
                ResolveExpr(expr, ref curSegment, access);

                // Create a new access for the same register, in case there's an outer
                // access modifier.
                access = Core.DataAccessRegister.ForRegister(expr.GetSpan(), registerIndex);
                return(access);
            }

            this.foundErrors = true;
            session.AddMessage(
                Diagnostics.MessageKind.Error,
                Diagnostics.MessageCode.InvalidAccess,
                "expression has no address",
                expr.GetSpan());
            return(null);
        }
Example #8
0
        private void ResolveExprLiteralStruct(Grammar.ASTNodeExprLiteralStruct exprLiteralStruct, ref int curSegment, Core.DataAccess output)
        {
            var type = TypeResolver.ResolveStruct(session, exprLiteralStruct.name, useDirectives, true);

            if (!type.IsResolved())
            {
                return;
            }

            var typeStruct     = type as Core.TypeStruct;
            var fieldNum       = TypeResolver.GetFieldNum(this.session, typeStruct);
            var fieldDestSpans = new Diagnostics.Span?[fieldNum];

            var fieldRegs = new int[fieldNum];

            for (var i = 0; i < fieldNum; i++)
            {
                fieldRegs[i] = funct.CreateRegister(
                    TypeResolver.GetFieldType(this.session, typeStruct, i), false);
            }

            var fieldRegAccesses = new Core.DataAccess[fieldNum];

            for (var i = 0; i < fieldNum; i++)
            {
                fieldRegAccesses[i] =
                    Core.DataAccessRegister.ForRegister(exprLiteralStruct.name.GetSpan(), fieldRegs[i]);
            }

            foreach (var fieldInit in exprLiteralStruct.fields)
            {
                var name = NameResolver.Resolve(fieldInit.name);

                int fieldIndex;
                if (!this.session.GetStruct(typeStruct.structIndex).fieldNames.FindByName(name, out fieldIndex))
                {
                    this.foundErrors = true;
                    session.AddMessage(
                        Diagnostics.MessageKind.Error,
                        Diagnostics.MessageCode.Unknown,
                        "unknown field '" + name.GetString() + "' in '" +
                        type.GetString(this.session) + "'",
                        fieldInit.name.GetSpan());
                    continue;
                }

                if (fieldDestSpans[fieldIndex].HasValue)
                {
                    this.foundErrors = true;
                    session.AddMessage(
                        Diagnostics.MessageKind.Error,
                        Diagnostics.MessageCode.Unknown,
                        "duplicate field '" + name.GetString() + "' initialization",
                        fieldInit.name.GetSpan(),
                        fieldDestSpans[fieldIndex].Value);
                    continue;
                }

                fieldRegAccesses[fieldIndex].span = fieldInit.name.GetSpan();
                fieldDestSpans[fieldIndex]        = fieldInit.name.GetSpan();
                this.ResolveExpr(fieldInit.expr, ref curSegment, fieldRegAccesses[fieldIndex]);
            }

            var missingFields = new List <int>();

            for (var i = 0; i < fieldNum; i++)
            {
                if (!fieldDestSpans[i].HasValue)
                {
                    missingFields.Add(i);
                }
            }

            if (missingFields.Count > 0)
            {
                Core.Name fieldName;
                session.GetStruct(typeStruct.structIndex).fieldNames.FindByValue(missingFields[0], out fieldName);

                this.foundErrors = true;
                session.AddMessage(
                    Diagnostics.MessageKind.Error,
                    Diagnostics.MessageCode.Unknown,
                    "missing initializer" + (missingFields.Count > 1 ? "s" : "") +
                    " for field '" + fieldName.GetString() + "'" +
                    (missingFields.Count > 1 ? " and other " + (missingFields.Count - 1) : ""),
                    exprLiteralStruct.GetSpan());
            }
            else
            {
                var finalFieldDestSpans = new Diagnostics.Span[fieldNum];
                for (var i = 0; i < fieldNum; i++)
                {
                    finalFieldDestSpans[i] = fieldDestSpans[i].Value;
                }

                funct.AddInstruction(curSegment, Core.InstructionMoveLiteralStruct.Of(
                                         exprLiteralStruct.GetSpan(), output,
                                         typeStruct.structIndex, fieldRegAccesses, finalFieldDestSpans));
            }
        }