Browse Source

Added const expressions to the littlefoot compiler

tags/2021-05-28
jules 8 years ago
parent
commit
6db052524e
1 changed files with 160 additions and 78 deletions
  1. +160
    -78
      modules/juce_blocks_basics/littlefoot/juce_LittleFootCompiler.h

+ 160
- 78
modules/juce_blocks_basics/littlefoot/juce_LittleFootCompiler.h View File

@@ -110,7 +110,7 @@ private:
X(if_, "if") X(else_, "else") X(do_, "do") \
X(while_, "while") X(for_, "for") X(break_, "break") X(continue_, "continue") \
X(void_, "void") X(int_, "int") X(float_, "float") X(bool_, "bool") \
X(return_, "return") X(true_, "true") X(false_, "false")
X(return_, "return") X(true_, "true") X(false_, "false") X(const_, "const")
#define LITTLEFOOT_OPERATORS(X) \
X(semicolon, ";") X(dot, ".") X(comma, ",") X(hash, "#") \
@@ -144,7 +144,7 @@ private:
CodeLocation (const String& code) noexcept : program (code), location (program.getCharPointer()) {}
CodeLocation (const CodeLocation& other) noexcept : program (other.program), location (other.location) {}
void throwError (const String& message) const
[[noreturn]] void throwError (const String& message) const
{
int col = 1, line = 1;
@@ -205,7 +205,7 @@ private:
{
if (isIdentifierStart (*p))
{
String::CharPointerType end (p);
auto end = p;
while (isIdentifierBody (*++end)) {}
const size_t len = (size_t) (end - p);
@@ -329,7 +329,7 @@ private:
bool parseOctalLiteral()
{
String::CharPointerType t (p);
auto t = p;
int64 v = *t - '0';
if (v != 0) return false; // first digit of octal must be 0
@@ -380,6 +380,8 @@ private:
continue;
}
const bool isConstVariable = matchIf (Token::const_);
if (! matchesAnyTypeOrVoid())
throwErrorExpecting ("a global variable or function");
@@ -388,6 +390,9 @@ private:
if (matchIf (Token::openParen))
{
if (isConstVariable)
location.throwError ("Return type of a function cannot be const");
parseFunctionDeclaration (type, name);
continue;
}
@@ -395,19 +400,7 @@ private:
if (type == Type::void_)
location.throwError ("A variable type cannot be 'void'");
int arraySize = matchIf (Token::openBracket) ? parseIntegerLiteral() : 0;
if (arraySize > 0)
location.throwError ("Arrays not yet implemented!");
while (matchIf (Token::comma))
{
blockBeingParsed->addVariable (name, type, location);
name = parseIdentifier();
}
blockBeingParsed->addVariable (name, type, location);
match (Token::semicolon);
parseGlobalVariableDeclaraion (isConstVariable, type, name);
}
}
@@ -462,6 +455,54 @@ private:
location.throwError ("Unknown compiler directive");
}
void parseGlobalVariableDeclaraion (bool isConst, Type type, String name)
{
for (;;)
{
int arraySize = matchIf (Token::openBracket) ? parseIntegerLiteral() : 0;
if (arraySize > 0)
location.throwError ("Arrays not yet implemented!");
var constantInitialiser;
if (isConst)
constantInitialiser = parseConstantExpressionInitialiser (type);
blockBeingParsed->addVariable ({ name, type, true, isConst, constantInitialiser }, location);
if (matchIf (Token::comma))
{
name = parseIdentifier();
continue;
}
match (Token::semicolon);
break;
}
}
var parseConstantExpressionInitialiser (Type expectedType)
{
var result;
match (Token::assign);
auto e = parseExpression();
if (auto literal = dynamic_cast<LiteralValue*> (e->simplify (*this)))
{
result = literal->value;
if (getTypeOfVar (result) != expectedType)
location.throwError ("Expected a constant expression of type " + getTypeName (expectedType));
}
else
{
location.throwError ("Expected a constant expression");
}
return result;
}
void parseFunctionDeclaration (Type returnType, const String& name)
{
auto f = allocate<Function>();
@@ -469,7 +510,7 @@ private:
while (matchesAnyType())
{
auto type = tokenToType (skip());
f->arguments.add ({ parseIdentifier(), type });
f->arguments.add ({ parseIdentifier(), type, false, false, 0 });
if (f->arguments.size() > 127)
location.throwError ("Too many function arguments");
@@ -547,7 +588,8 @@ private:
if (matchIf (Token::plusplus)) return matchEndOfStatement (parsePreIncDec (Token::plus));
if (matchIf (Token::minusminus)) return matchEndOfStatement (parsePreIncDec (Token::minus));
if (matchesAny (Token::openParen)) return matchEndOfStatement (parseFactor());
if (matchesAnyType()) return parseVariableDeclaration (tokenToType (skip()));
if (matchIf (Token::const_)) return parseVariableDeclaration (true);
if (matchesAnyType()) return parseVariableDeclaration (false);
if (matchesAny (Token::identifier, Token::literal, Token::minus))
return matchEndOfStatement (parseExpression());
@@ -758,43 +800,57 @@ private:
return returnStatement;
}
StatementPtr parseVariableDeclaration (Type type)
StatementPtr parseVariableDeclaration (bool isConst)
{
if (isConst && ! matchesAnyType())
throwErrorExpecting ("a type");
auto type = tokenToType (skip());
for (StatementPtr result = nullptr;;)
{
auto name = parseIdentifier();
auto loc = location;
blockBeingParsed->addVariable (name, type, loc);
auto assignedValue = matchIf (Token::assign) ? parseExpression() : nullptr;
if (auto literal = dynamic_cast<LiteralValue*> (assignedValue))
if (static_cast<double> (literal->value) == 0)
assignedValue = nullptr;
if (assignedValue != nullptr || ! blockBeingParsed->isMainBlockOfFunction) // no need to assign 0 for variables in the outer scope
if (isConst)
{
auto constantValue = parseConstantExpressionInitialiser (type);
blockBeingParsed->addVariable ({ name, type, false, true, constantValue }, loc);
}
else
{
if (assignedValue == nullptr)
assignedValue = allocate<LiteralValue> (loc, blockBeingParsed, (int) 0);
blockBeingParsed->addVariable ({ name, type, false, false, {} }, loc);
auto assignment = allocate<Assignment> (loc, blockBeingParsed, name, assignedValue, false);
auto assignedValue = matchIf (Token::assign) ? parseExpression() : nullptr;
if (result == nullptr)
{
result = assignment;
}
else
if (auto literal = dynamic_cast<LiteralValue*> (assignedValue))
if (static_cast<double> (literal->value) == 0)
assignedValue = nullptr;
if (assignedValue != nullptr || ! blockBeingParsed->isMainBlockOfFunction) // no need to assign 0 for variables in the outer scope
{
auto block = dynamic_cast<BlockPtr> (result);
if (assignedValue == nullptr)
assignedValue = allocate<LiteralValue> (loc, blockBeingParsed, (int) 0);
if (block == nullptr)
auto assignment = allocate<Assignment> (loc, blockBeingParsed, name, assignedValue, false);
if (result == nullptr)
{
block = allocate<BlockStatement> (loc, blockBeingParsed, functions.getLast(), false);
block->statements.add (result);
result = block;
result = assignment;
}
else
{
auto block = dynamic_cast<BlockPtr> (result);
if (block == nullptr)
{
block = allocate<BlockStatement> (loc, blockBeingParsed, functions.getLast(), false);
block->statements.add (result);
result = block;
}
block->statements.add (assignment);
block->statements.add (assignment);
}
}
}
@@ -848,7 +904,7 @@ private:
String parseIdentifier()
{
String name = currentValue.toString();
auto name = currentValue.toString();
match (Token::identifier);
return name;
}
@@ -1104,12 +1160,15 @@ private:
{
Expression (const CodeLocation& l, BlockPtr parent) noexcept : Statement (l, parent) {}
virtual Type getType (CodeGenerator&) const = 0;
virtual ExpPtr simplify (SyntaxTreeBuilder&) override { return this; }
};
struct Variable
{
String name;
Type type;
bool isGlobal, isConst;
var constantValue;
};
//==============================================================================
@@ -1266,38 +1325,43 @@ private:
+ parentBlock->variables.size());
}
const Array<Variable>& getGlobalVariables() const noexcept
{
return parentBlock != nullptr ? parentBlock->getGlobalVariables() : variables;
}
const Array<Variable>& getGlobalVariables() const noexcept { return parentBlock != nullptr ? parentBlock->getGlobalVariables() : variables; }
const Array<Variable>& getGlobalConstants() const noexcept { return parentBlock != nullptr ? parentBlock->getGlobalConstants() : constants; }
Type getVariableType (const String& name, const CodeLocation& locationForError) const
const Variable& getVariable (const String& name, const CodeLocation& locationForError) const
{
for (auto& v : constants)
if (v.name == name)
return v;
for (auto& v : variables)
if (v.name == name)
return v.type;
return v;
if (! isMainBlockOfFunction)
return parentBlock->getVariableType (name, locationForError);
return parentBlock->getVariable (name, locationForError);
for (auto& v : function->arguments)
if (v.name == name)
return v.type;
return v;
for (auto& v : getGlobalConstants())
if (v.name == name)
return v;
for (auto& v : getGlobalVariables())
if (v.name == name)
return v.type;
return v;
locationForError.throwError ("Unknown variable '" + name + "'");
return {};
}
void addVariable (const String& name, Type type, const CodeLocation& locationForError)
void addVariable (Variable v, const CodeLocation& locationForError)
{
if (indexOf (variables, name) >= 0)
locationForError.throwError ("Variable '" + name + "' already exists");
if (indexOf (variables, v.name) >= 0 || indexOf (constants, v.name) >= 0)
locationForError.throwError ("Variable '" + v.name + "' already exists");
variables.add ({ name, type });
(v.isConst ? constants : variables).add (v);
}
static int indexOf (const Array<Variable>& vars, const String& name) noexcept
@@ -1311,7 +1375,7 @@ private:
Function* function;
Array<StatementPtr> statements;
Array<Variable> variables;
Array<Variable> variables, constants;
bool isMainBlockOfFunction;
};
@@ -1356,7 +1420,7 @@ private:
Statement* simplify (SyntaxTreeBuilder& stb) override
{
condition = dynamic_cast<ExpPtr> (condition->simplify (stb));
condition = condition->simplify (stb);
trueBranch = trueBranch->simplify (stb);
falseBranch = falseBranch != nullptr ? falseBranch->simplify (stb) : nullptr;
@@ -1402,11 +1466,11 @@ private:
visit (condition); visit (trueBranch); visit (falseBranch);
}
Statement* simplify (SyntaxTreeBuilder& stb) override
ExpPtr simplify (SyntaxTreeBuilder& stb) override
{
condition = dynamic_cast<ExpPtr> (condition->simplify (stb));
trueBranch = dynamic_cast<ExpPtr> (trueBranch->simplify (stb));
falseBranch = dynamic_cast<ExpPtr> (falseBranch->simplify (stb));
condition = condition->simplify (stb);
trueBranch = trueBranch->simplify (stb);
falseBranch = falseBranch->simplify (stb);
if (auto literal = dynamic_cast<LiteralValue*> (condition))
return literal->value ? trueBranch : falseBranch;
@@ -1569,7 +1633,17 @@ private:
Type getType (CodeGenerator&) const override
{
return parentBlock->getVariableType (name, location);
return parentBlock->getVariable (name, location).type;
}
ExpPtr simplify (SyntaxTreeBuilder& stb) override
{
auto& v = parentBlock->getVariable (name, location);
if (v.isConst)
return stb.allocate<LiteralValue> (location, parentBlock, v.constantValue);
return this;
}
String name;
@@ -1626,9 +1700,9 @@ private:
visit (source);
}
Statement* simplify (SyntaxTreeBuilder& stb) override
ExpPtr simplify (SyntaxTreeBuilder& stb) override
{
source = dynamic_cast<ExpPtr> (source->simplify (stb));
source = source->simplify (stb);
if (auto literal = dynamic_cast<LiteralValue*> (source))
{
@@ -1745,7 +1819,7 @@ private:
visit (lhs); visit (rhs);
}
Statement* simplifyFloat (double a, double b, LiteralValue* literal)
ExpPtr simplifyFloat (double a, double b, LiteralValue* literal)
{
if (operation == Token::plus) { literal->value = a + b; return literal; }
if (operation == Token::minus) { literal->value = a - b; return literal; }
@@ -1760,14 +1834,14 @@ private:
return this;
}
Statement* simplifyBool (bool a, bool b, LiteralValue* literal)
ExpPtr simplifyBool (bool a, bool b, LiteralValue* literal)
{
if (operation == Token::logicalOr) { literal->value = a || b; return literal; }
if (operation == Token::logicalAnd) { literal->value = a && b; return literal; }
return this;
}
Statement* simplifyInt (int a, int b, LiteralValue* literal)
ExpPtr simplifyInt (int a, int b, LiteralValue* literal)
{
if (operation == Token::plus) { literal->value = a + b; return literal; }
if (operation == Token::minus) { literal->value = a - b; return literal; }
@@ -1790,10 +1864,10 @@ private:
return this;
}
Statement* simplify (SyntaxTreeBuilder& stb) override
ExpPtr simplify (SyntaxTreeBuilder& stb) override
{
lhs = dynamic_cast<ExpPtr> (lhs->simplify (stb));
rhs = dynamic_cast<ExpPtr> (rhs->simplify (stb));
lhs = lhs->simplify (stb);
rhs = rhs->simplify (stb);
if (auto literal1 = dynamic_cast<LiteralValue*> (lhs))
{
@@ -1858,7 +1932,7 @@ private:
Type getType (CodeGenerator&) const override
{
return parentBlock->getVariableType (target, location);
return parentBlock->getVariable (target, location).type;
}
void visitSubStatements (Statement::Visitor& visit) const override
@@ -1866,9 +1940,9 @@ private:
visit (newValue);
}
Statement* simplify (SyntaxTreeBuilder& stb) override
ExpPtr simplify (SyntaxTreeBuilder& stb) override
{
newValue = dynamic_cast<ExpPtr> (newValue->simplify (stb));
newValue = newValue->simplify (stb);
return this;
}
@@ -2015,6 +2089,14 @@ private:
visit (arg);
}
ExpPtr simplify (SyntaxTreeBuilder& stb) override
{
for (auto& arg : arguments)
arg = arg->simplify (stb);
return this;
}
String functionName;
Array<ExpPtr> arguments;
};
@@ -2033,10 +2115,10 @@ private:
visit (object); visit (index);
}
Statement* simplify (SyntaxTreeBuilder& stb) override
ExpPtr simplify (SyntaxTreeBuilder& stb) override
{
object = dynamic_cast<ExpPtr> (object->simplify (stb));
index = dynamic_cast<ExpPtr> (index->simplify (stb));
object = object->simplify (stb);
index = index->simplify (stb);
return this;
}


Loading…
Cancel
Save