Ejemplo n.º 1
0
        public Translator(CompilerContext context)
        {
            MethodGenerator = new MethodGenerator(context);

            _context = context;
            _lexer = context.Lexer;
            _symbolTable = context.SymbolTable;
            _lastParsedPosition = _lexer.TokenStartPosition;
            _lexeme = string.Empty;
        }
Ejemplo n.º 2
0
        private IrisType ProcessArrayAccess(FilePosition fp, Symbol symbol, SymbolLoadMode mode)
        {
            IrisType symbolType = symbol.Type;
            IrisType resultType = IrisType.Invalid;
            if (symbolType != IrisType.Invalid)
            {
                if (!symbolType.IsArray)
                {
                    AddError(fp, string.Format("Symbol '{0}' is not an array, but is being used as an array.", _lexeme));
                }
                else
                {
                    EmitLoadSymbol(symbol, SymbolLoadMode.Dereference);
                    resultType = symbol.Type.GetElementType();
                }
            }

            FilePosition indexerPosition = _lexer.TokenStartPosition;
            IrisType indexerType = ParseExpression();
            if (indexerType != IrisType.Integer)
                AddError(indexerPosition, "Expecting integer value as array index.");

            Expect(Token.ChrCloseBracket);

            if (resultType != IrisType.Invalid)
            {
                if (mode == SymbolLoadMode.ElementAddress)
                {
                    MethodGenerator.LoadElementAddress(resultType);
                    resultType = resultType.MakeByRefType();
                }
                else if (mode == SymbolLoadMode.Element)
                {
                    MethodGenerator.LoadElement(resultType);
                }
            }

            return resultType;
        }
        protected void ParseMethod(bool isFunction)
        {
            FilePosition namePosition = _lexer.TokenStartPosition;

            if (!Accept(Token.Identifier))
            {
                AddError(namePosition, "Expecting procedure or function name.");
                SkipToNextEnd();
                return;
            }

            string methodName = _lexeme;

            if (!ValidateName(namePosition, methodName, global: true))
            {
                methodName = (_nextUniqueName++).ToString();
            }

            List <Tuple <Variable, FilePosition> > parameterList = new List <Tuple <Variable, FilePosition> >();

            if (Accept(Token.ChrOpenParen) && !Accept(Token.ChrCloseParen))
            {
                ParseVariableList(parameterList, isArgumentList: true);
                Expect(Token.ChrCloseParen);
            }

            IrisType returnType = IrisType.Void;

            if (Accept(Token.ChrColon))
            {
                returnType = ParseType();
                if (!isFunction)
                {
                    AddErrorAtTokenStart("Procedure cannot have return value.");
                }
            }
            else if (isFunction)
            {
                AddErrorAtTokenStart("Expecting return type for function.");
                returnType = IrisType.Invalid;
            }

            Expect(Token.ChrSemicolon);

            // We've now parsed the method header.  We can now create the method symbol and parse
            // the body of the method.
            IrisType method;

            Variable[] parameters = parameterList.Select(p => p.Item1).ToArray();
            method = isFunction ?
                     (IrisType)Function.Create(returnType, parameters) :
                     Procedure.Create(parameterList.Select(p => p.Item1).ToArray());

            Symbol methodSymbol = _symbolTable.OpenMethod(methodName, method);

            // Add argument symbols for all of the parameters
            foreach (Tuple <Variable, FilePosition> param in parameterList)
            {
                if (ValidateName(param.Item2, param.Item1.Name, global: false))
                {
                    _symbolTable.Add(param.Item1.Name, param.Item1.Type, StorageClass.Argument);
                }
            }

            List <Variable> locals = new List <Variable>();

            if (isFunction)
            {
                // Create a local variable for the return value
                _symbolTable.Add(methodName, returnType, StorageClass.Local);
                locals.Add(new Variable(returnType, methodName));
            }

            if (Accept(Token.KwVar))
            {
                List <Tuple <Variable, FilePosition> > localsAndPositions = new List <Tuple <Variable, FilePosition> >();
                ParseVariableList(localsAndPositions, isArgumentList: false);
                Accept(Token.ChrSemicolon);

                foreach (Tuple <Variable, FilePosition> localDecl in localsAndPositions)
                {
                    Variable local     = localDecl.Item1;
                    string   localName = local.Name;
                    if (ValidateName(localDecl.Item2, localName, global: false))
                    {
                        _symbolTable.Add(localName, local.Type, StorageClass.Local);
                        locals.Add(local);
                    }
                }
            }

            FilePosition begin = _lexer.TokenStartPosition;

            MethodGenerator.BeginMethod(methodSymbol.Name, returnType, parameters, locals.ToArray(), false, _context.FilePath);
            MethodGenerator.EmitNonCodeLineInfo(begin.Expand(5 /* Length of "begin" */));

            // Initialize locals if needed
            foreach (Variable local in locals)
            {
                InitializeVariableIfNeeded(begin, local);
            }

            // Parse the body of the method
            Expect(Token.KwBegin);
            ParseStatements(Token.KwEnd);

            if (isFunction)
            {
                MethodGenerator.PushLocal(0);
            }

            MethodGenerator.EndMethod();

            _symbolTable.CloseMethod();
        }
Ejemplo n.º 4
0
 internal void Add(FilePosition fp, string error)
 {
     _errors.Add(new Error(fp, error));
 }
Ejemplo n.º 5
0
 public Error(FilePosition fp, string error)
 {
     Position = fp;
     Text     = error;
 }
Ejemplo n.º 6
0
        internal void Add(int line, int column, string error)
        {
            FilePosition fp = new FilePosition(line, column);

            Add(fp, error);
        }
        protected void ImportGlobalField(
            FilePosition fp,
            string symbolName,
            ImportedModule module,
            string declaringTypeName,
            string fieldName)
        {
            ImportedType declaringType = module.TryGetTypeByName(declaringTypeName);
            if (declaringType == null)
            {
                CompileErrors.Add(fp, String.Format("Cannot find imported type '{0}'.", declaringTypeName));
                return;
            }

            ImportedField field = declaringType.TryGetPublicStaticField(fieldName);
            if (field == null)
            {
                CompileErrors.Add(fp, String.Format("Cannot find imported field '{0}.{1}'.", declaringTypeName, fieldName));
                return;
            }

            IrisType fieldType = field.FieldType;
            if (fieldType == IrisType.Invalid)
            {
                CompileErrors.Add(fp, String.Format("Type of field '{0}.{1}' is not supported by the language.", declaringTypeName, fieldName));
                return;
            }

            SymbolTable.Add(symbolName, field.FieldType, StorageClass.Global, field);
        }
 public void BeginSourceLine(FilePosition fp)
 {
     if (_outputEnabled && _emitDebugInfo)
     {
         _lineStart = fp;
         _isSourceLine = true;
     }
 }
Ejemplo n.º 9
0
        private IrisType ApplyTypeRules(FilePosition fp, IrisType lhs, IrisType rhs, bool boolResult = false)
        {
            // If there was a previous semantic error, don't apply any further rules.
            if (lhs == IrisType.Invalid || rhs == IrisType.Invalid)
                return IrisType.Invalid;

            string semanticError = null;
            if (lhs == IrisType.Void || rhs == IrisType.Void)
                semanticError = "Cannot apply operator to procedure call.";
            else if (lhs.IsByRef || rhs.IsByRef)
                semanticError = "Cannot take address of expression.";
            else if (lhs != rhs)
                semanticError = "Type mismatch error.";
            else if (!lhs.IsPrimitive)
                semanticError = "Operator requires a primitive type (boolean, integer, or string).";

            if (semanticError != null)
            {
                AddError(fp, semanticError);
                return IrisType.Invalid;
            }
            else
            {
                return boolResult ? IrisType.Boolean : lhs;
            }
        }
Ejemplo n.º 10
0
        private Symbol LookupSymbol(FilePosition symbolPosition, string name)
        {
            Symbol sym = _symbolTable.Lookup(name);
            if (sym == null)
            {
                // Undefined symbol.  Emit an error and "fake" the symbol so we can continue.
                AddError(symbolPosition, string.Format("Symbol '{0}' is undefined.", name));
                sym = _symbolTable.CreateUndefinedSymbol(name);
            }

            return sym;
        }
Ejemplo n.º 11
0
        protected Operator AcceptOperator(Operator[] map)
        {
            Operator result = map[(int)_lexer.CurrentToken];
            if (result != Operator.None)
            {
                _lastParsedPosition = _lexer.TokenEndPosition;
                _lexer.MoveNext();
            }

            return result;
        }
        private IrisType ProcessCall(FilePosition fp, Symbol symbol, bool skipArgList)
        {
            ParsedCallSyntax = true;

            IrisType symbolType = symbol.Type;

            if (!symbolType.IsMethod)
            {
                // Variables can have the same name as functions.  If the symbol is not a method,
                // try looking up the same name in the global scope.  If the global symbol is a
                // method, use it instead.
                Symbol globalSym = _symbolTable.LookupGlobal(symbol.Name);
                if (globalSym != null && globalSym.Type.IsMethod)
                {
                    symbol     = globalSym;
                    symbolType = symbol.Type;
                }
            }

            IrisType resultType    = IrisType.Invalid;
            bool     semanticError = symbolType == IrisType.Invalid;

            if (!symbolType.IsMethod && !semanticError)
            {
                semanticError = true;
                AddError(fp, string.Format("Symbol '{0}' is not a procedure or function.", _lexeme));
            }

            string symbolTypeName = symbolType.IsFunction ? "function" : "procedure";
            Method method         = symbolType as Method;

            Variable[] methodParams = method?.GetParameters();
            int        count        = 0;

            if (!skipArgList && !Accept(Token.ChrCloseParen))
            {
                do
                {
                    FilePosition argPosition = _lexer.TokenStartPosition;

                    if (methodParams != null && count < methodParams.Length)
                    {
                        Variable param     = methodParams[count];
                        IrisType paramType = param.Type;
                        IrisType argType   = ParseExpression(paramType.IsByRef ? SymbolLoadMode.Address : SymbolLoadMode.Dereference);

                        if (paramType != IrisType.Invalid && argType != IrisType.Invalid && paramType != argType)
                        {
                            if (paramType.IsByRef && !argType.IsByRef)
                            {
                                AddError(argPosition, "Cannot take address of constant, call, or expression.");
                            }
                            else
                            {
                                AddError(argPosition, string.Format(
                                             "Argument type doesn't match parameter '{0}' of {1} '{2}'",
                                             param.Name,
                                             symbolTypeName,
                                             symbol.Name));
                            }
                        }
                    }
                    else
                    {
                        // Undefined method or too many arguments.  Parse the argument without validation.
                        ParseExpression();
                    }

                    count++;
                }while (Accept(Token.ChrComma));

                Expect(Token.ChrCloseParen);
            }

            // Verify argument count
            if (methodParams != null && methodParams.Length != count)
            {
                AddError(fp, string.Format(
                             "Wrong number of arguments for {0} '{1}'.  {2} expected.  {3} provided.",
                             symbolTypeName,
                             symbol.Name,
                             methodParams.Length,
                             count));
            }

            if (!semanticError)
            {
                MethodGenerator.Call(symbol);
                resultType = symbolType.IsFunction ? ((Function)symbolType).ReturnType : IrisType.Void;
            }

            return(resultType);
        }
        protected IrisType ParseBaseExpression(SymbolLoadMode mode)
        {
            FilePosition fp = _lastParsedPosition;

            if (Accept(Token.Identifier))
            {
                Symbol symbol = LookupSymbol(fp, _lexeme);

                if (Accept(Token.ChrOpenBracket))
                {
                    return(ProcessArrayAccess(fp, symbol, mode == SymbolLoadMode.Address ? SymbolLoadMode.ElementAddress : SymbolLoadMode.Element));
                }
                if (Accept(Token.ChrOpenParen))
                {
                    return(ProcessCall(fp, symbol, skipArgList: false));
                }

                IrisType type = symbol.Type;
                if (type.IsMethod)
                {
                    return(ProcessCall(fp, symbol, skipArgList: true));
                }
                if (type != IrisType.Invalid)
                {
                    EmitLoadSymbol(symbol, mode);
                }

                if (mode == SymbolLoadMode.Address && !type.IsByRef)
                {
                    return(type.MakeByRefType());
                }
                else if (mode == SymbolLoadMode.Dereference)
                {
                    return(DerefType(type));
                }
                else
                {
                    return(type);
                }
            }
            else if (Accept(Token.KwTrue))
            {
                MethodGenerator.PushIntConst(1);
                return(IrisType.Boolean);
            }
            else if (Accept(Token.KwFalse))
            {
                MethodGenerator.PushIntConst(0);
                return(IrisType.Boolean);
            }
            else if (Accept(Token.Number))
            {
                MethodGenerator.PushIntConst(_lastIntegerLexeme);
                return(IrisType.Integer);
            }
            else if (Accept(Token.String))
            {
                MethodGenerator.PushString(_lexeme);
                return(IrisType.String);
            }
            else if (Accept(Token.ChrOpenParen))
            {
                IrisType type = ParseExpression(mode);
                Expect(Token.ChrCloseParen);
                return(type);
            }

            AddError(fp, "Expecting expression.");
            return(IrisType.Invalid);
        }
        protected void ParseProgram()
        {
            string programName = "program";

            if (Accept(Token.KwProgram))
            {
                if (Accept(Token.Identifier))
                {
                    programName = _lexeme;
                }
                else
                {
                    AddErrorAtTokenStart("Expecting program name.");
                }

                Expect(Token.ChrSemicolon);
            }

            _context.Emitter.BeginProgram(programName, _context.Importer.ImportedAssemblies);

            List <Tuple <Variable, FilePosition> > globals = new List <Tuple <Variable, FilePosition> >();

            if (Accept(Token.KwVar))
            {
                ParseVariableList(globals, isArgumentList: false);
                foreach (Tuple <Variable, FilePosition> globalDecl in globals)
                {
                    Variable global = globalDecl.Item1;
                    if (ValidateName(globalDecl.Item2, global.Name, global: true))
                    {
                        Symbol globalSymbol = _symbolTable.Add(global.Name, global.Type, StorageClass.Global);
                        _context.Emitter.DeclareGlobal(globalSymbol);
                    }
                }
            }

            FilePosition blockBegin = _lexer.TokenStartPosition;

            while (!Accept(Token.KwBegin))
            {
                if (Accept(Token.Eof))
                {
                    AddErrorAtLastParsedPosition("Unexpected end of file looking for main block.");
                    return;
                }
                else if (Accept(Token.KwFunction))
                {
                    ParseMethod(isFunction: true);
                }
                else if (Accept(Token.KwProcedure))
                {
                    ParseMethod(isFunction: false);
                }
                else if (Accept(Token.KwVar))
                {
                    AddErrorAtTokenStart("Global variables must be declared before the first function or procedure.");
                    List <Tuple <Variable, FilePosition> > unused = new List <Tuple <Variable, FilePosition> >();
                    ParseVariableList(unused, isArgumentList: false);
                }
                else if (!Accept(Token.ChrSemicolon))
                {
                    AddErrorAtTokenStart("Expecting 'function', 'procedure', or 'begin'.");
                    SkipToNextEnd();
                }

                blockBegin = _lexer.TokenStartPosition;
            }

            // We are now at the main block
            IrisType mainMethod = Procedure.Create(new Variable[0]);
            Symbol   mainSymbol = _symbolTable.OpenMethod("$.main", mainMethod);

            MethodGenerator.BeginMethod(mainSymbol.Name, IrisType.Void, new Variable[0], new Variable[0], true, _context.FilePath);
            MethodGenerator.EmitNonCodeLineInfo(blockBegin.Expand(5 /* Length of "begin" */));

            // Initialize global variables if needed
            foreach (Tuple <Variable, FilePosition> globalDecl in globals)
            {
                InitializeVariableIfNeeded(blockBegin, globalDecl.Item1);
            }

            ParseStatements(Token.KwEnd);

            MethodGenerator.EndMethod();

            Accept(Token.ChrPeriod);
            Expect(Token.Eof);

            _context.Emitter.EndProgram();
        }
        protected void ParseStatement(bool allowEmpty = false)
        {
            FilePosition statementStart = _lexer.TokenStartPosition;

            MethodGenerator.BeginSourceLine(statementStart);
            if (Accept(Token.KwFor))
            {
                Symbol       iterator;
                FilePosition fp = _lexer.TokenStartPosition;
                if (!Accept(Token.Identifier))
                {
                    AddError(fp, "Expecting integer identifier.");
                    SkipStatement();
                    return;
                }

                // Initial assignment
                iterator = LookupSymbol(fp, _lexeme);
                VerifyExpressionType(fp, DerefType(iterator.Type), IrisType.Integer);
                bool byRef = iterator.Type.IsByRef;
                if (byRef)
                {
                    EmitLoadSymbol(iterator, SymbolLoadMode.Raw);
                }

                Expect(Token.ChrAssign);
                fp = _lexer.TokenStartPosition;
                IrisType rhs = ParseExpression();
                VerifyExpressionType(fp, rhs, IrisType.Integer);

                if (byRef)
                {
                    MethodGenerator.Store(rhs);
                }
                else
                {
                    EmitStoreSymbol(iterator);
                }

                Expect(Token.KwTo);

                // Loop start and condition
                int loopLabel = GetNextLabel();
                MethodGenerator.Label(loopLabel);
                EmitLoadSymbol(iterator, SymbolLoadMode.Dereference);
                fp  = _lexer.TokenStartPosition;
                rhs = ParseExpression();
                VerifyExpressionType(fp, rhs, IrisType.Integer);
                int exitLabel = GetNextLabel();
                MethodGenerator.BranchCondition(Operator.GreaterThan, exitLabel);

                // Loop body
                Expect(Token.KwDo);
                FilePosition forEndPosition = _lastParsedPosition;
                MethodGenerator.EndSourceLine(forEndPosition);
                ParseStatement();

                // Loop end
                MethodGenerator.BeginSourceLine(statementStart); // Source position is the same as the loop start.
                Increment(iterator);
                MethodGenerator.Goto(loopLabel);
                MethodGenerator.Label(exitLabel);
                MethodGenerator.EndSourceLine(forEndPosition);
            }
            else if (Accept(Token.KwWhile))
            {
                int loopLabel = GetNextLabel();
                MethodGenerator.Label(loopLabel);

                FilePosition fp   = _lexer.TokenStartPosition;
                IrisType     type = ParseExpression();
                VerifyExpressionType(fp, type, IrisType.Boolean);
                int exitLabel = GetNextLabel();
                MethodGenerator.BranchFalse(exitLabel);

                Expect(Token.KwDo);

                MethodGenerator.EndSourceLine(_lastParsedPosition);

                ParseStatement();
                MethodGenerator.Goto(loopLabel);
                MethodGenerator.Label(exitLabel);
            }
            else if (Accept(Token.KwRepeat))
            {
                int loopLabel = GetNextLabel();
                MethodGenerator.Label(loopLabel);
                MethodGenerator.EmitNonCodeLineInfo(new SourceRange(statementStart, _lastParsedPosition));

                ParseStatements(Token.KwUntil);

                FilePosition fp   = _lexer.TokenStartPosition;
                IrisType     type = ParseExpression();
                VerifyExpressionType(fp, type, IrisType.Boolean);
                MethodGenerator.BranchFalse(loopLabel);

                MethodGenerator.EndSourceLine(_lastParsedPosition);
            }
            else if (Accept(Token.KwIf))
            {
                ParseIf();
            }
            else if (Accept(Token.KwBegin))
            {
                MethodGenerator.EmitNonCodeLineInfo(new SourceRange(statementStart, _lastParsedPosition));
                ParseStatements(Token.KwEnd);
            }
            else if (Accept(Token.Identifier))
            {
                FilePosition fp         = _lexer.TokenStartPosition;
                string       symbolName = _lexeme;
                Symbol       symbol     = LookupSymbol(fp, symbolName);
                IrisType     lhs        = symbol.Type;
                bool         assign     = false;
                bool         isArray    = false;
                if (Accept(Token.ChrOpenBracket))
                {
                    // Assignment to an array element.
                    isArray = true;
                    lhs     = ProcessArrayAccess(fp, symbol, SymbolLoadMode.Raw);
                }
                if (Accept(Token.ChrAssign))
                {
                    assign = true;
                    bool indirectAssign = false;

                    if (lhs.IsByRef)
                    {
                        lhs = lhs.GetElementType();
                        EmitLoadSymbol(symbol, SymbolLoadMode.Raw);
                        indirectAssign = true;
                    }

                    FilePosition exprPosition = _lexer.TokenStartPosition;
                    IrisType     rhs          = ParseExpression();

                    if (lhs.IsMethod)
                    {
                        AddError(fp, "Cannot assign to result of function or procedure call.");
                    }
                    else if (lhs != IrisType.Invalid)
                    {
                        if (rhs == IrisType.Void)
                        {
                            AddError(fp, "Cannot use procedure in assignment statement.");
                        }
                        else if (rhs != IrisType.Invalid && rhs != lhs)
                        {
                            AddError(exprPosition, string.Format("Cannot assign to '{0}' (type mismatch error).", symbolName));
                        }

                        if (isArray)
                        {
                            MethodGenerator.StoreElement(lhs);
                        }
                        else if (indirectAssign)
                        {
                            MethodGenerator.Store(lhs);
                        }
                        else
                        {
                            EmitStoreSymbol(symbol);
                        }
                    }
                }
                else if (isArray)
                {
                    // This is an array subscript.  Assignment is the only kind of statement that
                    // starts with an array subscript.
                    AddErrorAtTokenStart("Expecting ':='.");
                    SkipStatement();
                }

                if (!assign && !isArray)
                {
                    bool skipArgList = !Accept(Token.ChrOpenParen);
                    ProcessCall(fp, symbol, skipArgList);

                    if (symbol.Type.IsFunction)
                    {
                        MethodGenerator.Pop();
                    }
                }

                MethodGenerator.EndSourceLine(_lastParsedPosition);
            }
            else if (Accept(Token.KwElse))
            {
                AddErrorAtTokenStart("Cannot start statement with 'else' or unexpected ';' after if statement.");
                SkipStatement();
            }
            else if (!allowEmpty && !Accept(Token.ChrSemicolon))
            {
                AddErrorAtLastParsedPosition("Expecting statement.");
                SkipStatement();
            }
        }
Ejemplo n.º 16
0
        private IrisType ProcessCall(FilePosition fp, Symbol symbol, bool skipArgList)
        {
            ParsedCallSyntax = true;

            IrisType symbolType = symbol.Type;
            if (!symbolType.IsMethod)
            {
                // Variables can have the same name as functions.  If the symbol is not a method,
                // try looking up the same name in the global scope.  If the global symbol is a
                // method, use it instead.
                Symbol globalSym = _symbolTable.LookupGlobal(symbol.Name);
                if (globalSym != null && globalSym.Type.IsMethod)
                {
                    symbol = globalSym;
                    symbolType = symbol.Type;
                }
            }

            IrisType resultType = IrisType.Invalid;
            bool semanticError = symbolType == IrisType.Invalid;
            if (!symbolType.IsMethod && !semanticError)
            {
                semanticError = true;
                AddError(fp, string.Format("Symbol '{0}' is not a procedure or function.", _lexeme));
            }

            string symbolTypeName = symbolType.IsFunction ? "function" : "procedure";
            Method method = symbolType as Method;
            Variable[] methodParams = method?.GetParameters();
            int count = 0;
            if (!skipArgList && !Accept(Token.ChrCloseParen))
            {
                do
                {
                    FilePosition argPosition = _lexer.TokenStartPosition;

                    if (methodParams != null && count < methodParams.Length)
                    {
                        Variable param = methodParams[count];
                        IrisType paramType = param.Type;
                        IrisType argType = ParseExpression(paramType.IsByRef ? SymbolLoadMode.Address : SymbolLoadMode.Dereference);

                        if (paramType != IrisType.Invalid && argType != IrisType.Invalid && paramType != argType)
                        {
                            if (paramType.IsByRef && !argType.IsByRef)
                            {
                                AddError(argPosition, "Cannot take address of constant, call, or expression.");
                            }
                            else
                            {
                                AddError(argPosition, string.Format(
                                    "Argument type doesn't match parameter '{0}' of {1} '{2}'",
                                    param.Name,
                                    symbolTypeName,
                                    symbol.Name));
                            }
                        }
                    }
                    else
                    {
                        // Undefined method or too many arguments.  Parse the argument without validation.
                        ParseExpression();
                    }

                    count++;
                }
                while (Accept(Token.ChrComma));

                Expect(Token.ChrCloseParen);
            }

            // Verify argument count
            if (methodParams != null && methodParams.Length != count)
            {
                AddError(fp, string.Format(
                    "Wrong number of arguments for {0} '{1}'.  {2} expected.  {3} provided.",
                    symbolTypeName,
                    symbol.Name,
                    methodParams.Length,
                    count));
            }

            if (!semanticError)
            {
                MethodGenerator.Call(symbol);
                resultType = symbolType.IsFunction ? ((Function)symbolType).ReturnType : IrisType.Void;
            }

            return resultType;
        }
Ejemplo n.º 17
0
        protected bool Accept(Token token)
        {
            if (_lexer.CurrentToken == token)
            {
                if (token != Token.Eof)
                    _lastParsedPosition = _lexer.TokenEndPosition;

                if (token == Token.String || token == Token.Identifier)
                    _lexeme = _lexer.GetLexeme();
                else if (token == Token.Number)
                    _lastIntegerLexeme = _lexer.ParseInteger();

                _lexer.MoveNext();
                return true;
            }

            return false;
        }
Ejemplo n.º 18
0
        private bool ValidateName(FilePosition fp, string name, bool global)
        {
            if (name[0] == '$')
                AddError(fp, "Identifiers starting with '$' are reserved.");

            Symbol existing = global ? _symbolTable.LookupGlobal(name) : _symbolTable.LookupLocal(name);
            if (existing != null)
            {
                AddError(fp, string.Format("Cannot redefine symbol '{0}'.", name));
                return false;
            }

            return true;
        }
        public void EndSourceLine(FilePosition fp)
        {
            if (_outputEnabled && _isSourceLine)
            {
                _emitter.EmitLineInfo(new SourceRange(_lineStart, fp), _methodFileName ?? string.Empty);
                _isSourceLine = false;

                _methodFileName = null; // We only need to emit this for the first line
            }

            EmitDeferredInstructions();
        }
Ejemplo n.º 20
0
 private void VerifyExpressionType(FilePosition fp, IrisType actual, IrisType expected)
 {
     if (actual != expected)
         AddError(fp, string.Format("Expecting {0} expression.", expected));
 }
        protected void ImportMethod(
            FilePosition fp,
            string symbolName,
            ImportedModule module,
            string declaringTypeName,
            string methodName,
            bool instance,
            IrisType returnType,
            IrisType[] paramTypes)
        {
            ImportedType declaringType = module.TryGetTypeByName(declaringTypeName);
            if (declaringType == null)
            {
                CompileErrors.Add(fp, String.Format("Cannot find imported type '{0}'.", declaringTypeName));
                return;
            }

            ImportedMethod importedMethod = declaringType.TryFindMethod(methodName, instance, returnType, paramTypes);
            if (importedMethod == null)
            {
                CompileErrors.Add(fp, String.Format("Cannot find imported function or procedure '{0}.{1}'.", declaringTypeName, methodName));
                return;
            }

            Method method = importedMethod.ConvertToIrisMethod();
            bool containsInvalidType = method.ReturnType == IrisType.Invalid;
            foreach (Variable param in method.GetParameters())
            {
                if (containsInvalidType)
                    break;

                if (param.Type == IrisType.Invalid)
                    containsInvalidType = true;
            }

            if (containsInvalidType)
                CompileErrors.Add(fp, String.Format("The function or procedure '{0}.{1}' contains types that are not supported by the language.", declaringTypeName, methodName));
            else
                SymbolTable.Add(symbolName, method, StorageClass.Global, importedMethod);
        }
Ejemplo n.º 22
0
 protected void AddError(FilePosition fp, string error)
 {
     MethodGenerator.SetOutputEnabled(false);
     _context.CompileErrors.Add(fp, error);
 }
Ejemplo n.º 23
0
 internal void Add(FilePosition fp, string error)
 {
     _errors.Add(new Error(fp, error));
 }
Ejemplo n.º 24
0
        private void InitializeVariableIfNeeded(FilePosition fp, Variable variable)
        {
            IrisType varType = variable.Type;
            if (varType.IsArray || varType == IrisType.String)
            {
                // Variable needs to be initialized.
                Symbol varSymbol = _symbolTable.Lookup(variable.Name);
                if (varType.IsArray)
                {
                    MethodGenerator.InitArray(varSymbol, variable.SubRange);
                    if (varType.GetElementType() == IrisType.String)
                    {
                        // String arary - initialize all elements
                        EmitLoadSymbol(varSymbol, SymbolLoadMode.Raw);
                        Symbol initProc = LookupSymbol(fp, "$.initstrarray");
                        MethodGenerator.Call(initProc);
                    }
                }
                else
                {
                    // String
                    Symbol emptyStr = LookupSymbol(fp, "$.emptystr");
                    MethodGenerator.PushGlobal(emptyStr);
                    EmitStoreSymbol(varSymbol);
                }

                MethodGenerator.EmitDeferredInstructions();
            }
        }
Ejemplo n.º 25
0
 internal void Add(int line, int column, string error)
 {
     FilePosition fp = new FilePosition(line, column);
     Add(fp, error);
 }
Ejemplo n.º 26
0
        private IrisType ProcessArithemticOperator(FilePosition fp, IrisType lhs, IrisType rhs, Operator opr)
        {
            IrisType resultType = ApplyTypeRules(fp, lhs, rhs);
            if (resultType == IrisType.String)
            {
                if (opr != Operator.Add)
                    AddError(fp, "Only the '+' or comparison operators can be used on string values.");

                Symbol concat = LookupSymbol(fp, "concat");
                MethodGenerator.Call(concat);
            }
            else if (resultType == IrisType.Boolean)
            {
                AddError(fp, "Arithmetic operators cannot be applied to boolean values.");
                return IrisType.Invalid;
            }
            else
            {
                MethodGenerator.Operator(opr);
            }

            return resultType;
        }
Ejemplo n.º 27
0
 public Error(FilePosition fp, string error)
 {
     Position = fp;
     Text = error;
 }
 protected void AddError(FilePosition fp, string error)
 {
     MethodGenerator.SetOutputEnabled(false);
     _context.CompileErrors.Add(fp, error);
 }