예제 #1
0
void assertTypeBoolean(Symbol expression)
{
    Symbol type = typeOf(expression);
    if (type.atom() != atomBoolean)
        spanOf(expression).throwError("expression is of type " +
            typeToString(type) + ", Boolean expected");
}
예제 #2
0
Symbol parseSwitchStatement(CharacterSource* source)
{
    Span startSpan;
    static String switchKeyword("switch");
    if (!Space::parseKeyword(source, switchKeyword, &startSpan))
        return Symbol();
    Span span;
    Space::assertCharacter(source, '(', &span);
    Symbol expression = parseExpressionOrFail(source);
    Space::assertCharacter(source, ')', &span);
    Space::assertCharacter(source, '{', &span);
    Symbol defaultCase;

    CharacterSource s = *source;
    SymbolList cases;
    do {
        Symbol c = parseCase(source);
        if (!c.valid())
            break;
        if (c.atom() == atomDefaultCase) {
            if (defaultCase.valid())
                s.location().throwError(
                    "This switch statement already has a default case");
            defaultCase = c;
        }
        else
            cases.add(c);
    } while (true);
    Space::assertCharacter(source, '}', &span);
    return Symbol(atomSwitchStatement, expression, defaultCase,
        SymbolArray(cases), newSpan(startSpan + span));
}
예제 #3
0
Symbol parseExpressionStatement(CharacterSource* source)
{
    CharacterSource s = *source;
    Symbol expression = parseExpression(&s);
    if (!expression.valid())
        return Symbol();
    Span span;
    if (!Space::parseCharacter(&s, ';', &span))
        return Symbol();
    *source = s;
    if (expression.atom() != atomFunctionCall)
        source->location().throwError("Statement has no effect");
    return Symbol(atomExpressionStatement, expression,
        newSpan(spanOf(expression) + span));
}
예제 #4
0
 void compileFunction(Symbol functionDefinitionStatement)
 {
     if (functionDefinitionStatement.cache<FunctionDefinitionCache>()->
         getCompilingFlag()) {
         // TODO: Give more details about what's being evaluated and how that came to call this
         spanOf(functionDefinitionStatement).end().throwError(
             "Function called during its own compilation");
     }
     functionDefinitionStatement.cache<FunctionDefinitionCache>()->
         setCompilingFlag(true);
     _epilogueStack.push(SymbolLabel());
     //Symbol type = typeOf(functionDefinitionStatement);
     //Symbol returnType = type[1].symbol();
     //_returnTypeStack.push(returnType);
     int stackAdjust = offsetOf(functionDefinitionStatement);
     if (stackAdjust != 0)
         addAdjustStackPointer(-stackAdjust);
     _stackOffset = 0;
     compileStatementSequence(functionDefinitionStatement[4].array());
     Symbol type = typeOf(functionDefinitionStatement);
     Symbol returnType = type[1].symbol();
     int returnTypeSize = (sizeOf(returnType) + 3) & -4;
     int parametersSize = 0;
     SymbolArray parameterTypes = type[2].array();
     for (int i = 0; i < parameterTypes.count(); ++i)
         parametersSize += (sizeOf(parameterTypes[i]) + 3) & -4;
     if (_reachable && returnType.atom() != atomVoid) {
         // TODO: Give more details about how it got there
         spanOf(functionDefinitionStatement).end().throwError(
             "Control reaches end of non-Void function");
     }
     addLabel(_epilogueStack.pop());
     addLoadWordFromStackRelativeAddress(returnTypeSize + stackAdjust);
     addMoveBlock(0, stackAdjust + 4 + parametersSize, 1 + returnTypeSize/4);
     if (stackAdjust != 0)
         addAdjustStackPointer(stackAdjust);
     add(Symbol(atomReturn));
     //_returnTypeStack.pop();
     functionDefinitionStatement.cache<FunctionDefinitionCache>()->setCompilingFlag(false);
     functionDefinitionStatement[5].label().setTarget(_firstBasicBlock.target());
 }
예제 #5
0
void checkTypes(SymbolEntry entry, Symbol returnType)
{
    if (entry.isArray()) {
        SymbolList list;
        SymbolArray array = entry.array();
        for (int i = 0; i < array.count(); ++i)
            checkTypes(array[i], returnType);
    }
    if (!entry.isSymbol())
        return;
    Symbol symbol = entry.symbol();
    switch (symbol.atom()) {
        case atomLogicalOr:
        case atomLogicalAnd:
            assertTypeBoolean(symbol[1].symbol());
            assertTypeBoolean(symbol[2].symbol());
            break;
        case atomFunctionCall:
            {
                Symbol function = symbol[1].symbol();
                SymbolArray parameterTypes = typeOf(function)[2].array();
                SymbolArray argumentTypes = typeOf(symbol[2]).array();
                if (parameterTypes != argumentTypes)
                    spanOf(symbol).throwError(
                        "function requires arguments of types " +
                        typesToString(parameterTypes) +
                        " but passed arguments of types " +
                        typesToString(argumentTypes));
            }
            break;
        case atomFunctionDefinitionStatement:
            checkTypes(symbol[3], returnType);
            checkTypes(symbol[4], symbol[1].symbol());
            return;
        case atomVariableDefinitionStatement:
            {
                Symbol initializerType = typeOf(symbol[3]);
                Symbol variableType = typeOf(symbol[1]);
                if (variableType != initializerType)
                    spanOf(symbol).throwError("variable declared as type " +
                        typeToString(variableType) +
                        " but initialized with expression of type " +
                        typeToString(initializerType));
            }
            break;
        case atomIfStatement:
            assertTypeBoolean(symbol[1].symbol());
            break;
        case atomSwitchStatement:
            {
                Symbol type = typeOf(symbol[1]);
                SymbolArray cases = symbol[2].array();
                for (int i = 0; i < cases.count(); ++i) {
                    Symbol c = cases[i];
                    SymbolArray expressions = c[1].array();
                    for (int j = 0; j < expressions.count(); ++j) {
                        Symbol expression = expressions[j];
                        Symbol expressionType = typeOf(expression);
                        if (type != expressionType)
                            spanOf(expression).throwError(
                                "can't compare an expression of type " +
                                typeToString(type) +
                                " to an expression of type " +
                                typeToString(expressionType));
                    }
                }
            }
            break;
        case atomReturnStatement:
            {
                Symbol expression = symbol[1].symbol();
                Symbol type;
                if (expression.valid())
                    type = typeOf(expression);
                else
                    type = Symbol(atomVoid);
                if (type != returnType)
                    spanOf(symbol).throwError(
                        "returning an expression of type " +
                        typeToString(type) +
                        " from a function with return type " +
                        typeToString(returnType));
            }
            break;
        case atomIncludeStatement:
            {
                Symbol expression = symbol[1].symbol();
                Symbol type = typeOf(expression);
                if (type.atom() != atomString)
                    spanOf(expression).throwError(
                        "argument to include is of type " +
                        typeToString(type) + ", expected String");
            }
            break;
        case atomFromStatement:
            {
                Symbol expression = symbol[1].symbol();
                Symbol type = typeOf(expression);
                if (type.atom() != atomString)
                    spanOf(expression).throwError(
                        "argument to from is of type " + typeToString(type) +
                        ", expected String");
            }
            break;
        case atomWhileStatement:
        case atomUntilStatement:
        case atomForStatement:
            assertTypeBoolean(symbol[2].symbol());
            break;
        case atomGotoStatement:
            {
                Symbol expression = symbol[1].symbol();
                Symbol type = typeOf(expression);
                if (type.atom() != atomLabel)
                    if (type.atom() != atomLabel)
                        spanOf(expression).throwError(
                            "expression is of type " + typeToString(type) +
                            ", Label expected");
            }
            break;
        case atomEmit:
            // TODO: Check that type of argument is Sequence<Compiler.Instruction>
            break;
    }

    const SymbolTail* tail = symbol.tail();
    while (tail != 0) {
        checkTypes(tail->head(), returnType);
        tail = tail->tail();
    }
}