Skip to content

Commit

Permalink
Merge branch 'release/v3.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
danielzsh committed Nov 11, 2020
2 parents c545348 + 893532e commit a8a9257
Show file tree
Hide file tree
Showing 11 changed files with 402 additions and 163 deletions.
14 changes: 7 additions & 7 deletions .github/workflows/c-cpp.yml → .github/workflows/compile.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: C/C++ CI
name: Compile Spark

on:
pull_request:
Expand All @@ -15,17 +15,17 @@ jobs:
- uses: ilammy/[email protected]
- name: compile
run: |
cl main.cpp /Fe:spark-windows /std:c++latest
cl main.cpp /Fe:spark /std:c++latest
- name: run
run: |
spark-windows.exe test.spark
spark.exe test.spark
shell: cmd
- name: upload executable
uses: actions/upload-artifact@v2
with:
name: windows
path: |
spark-windows.exe
spark.exe
mac-and-ubuntu:
runs-on: ${{matrix.os}}
strategy:
Expand All @@ -36,15 +36,15 @@ jobs:
- uses: actions/checkout@v2
- name: compile
run: |
g++ -std=c++17 main.cpp -o spark-${{matrix.os}}
g++ -std=c++17 main.cpp -o spark
- name: run
run: |
./spark-${{matrix.os}} test.spark
./spark test.spark
shell: bash
- name: upload executable
uses: actions/upload-artifact@v2
with:
name: ${{matrix.os}}
path: |
spark-${{matrix.os}}
spark
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,6 @@ Debug/*
.vs/*
*.sln
*.vcxproj.*
*.vcxproj
*.vcxproj
spark.exe
*.obj
39 changes: 39 additions & 0 deletions Interpreter/Stack.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#pragma once
#include <string>
#include <variant>
#include <map>
#include <vector>
enum class ARType {
PROGRAM,
FUNCTION
};
using value = std::variant<int, double, std::string>;
class ActivationRecord {
public:
std::string name;
ARType type;
int nesting_level;
std::map<std::string, value> members;
ActivationRecord(ARType type, int nesting_level, std::string name = "") {
this->name = name;
this->type = type;
this->nesting_level = nesting_level;
this->members = members;
}
value& operator [] (std::string index) {
return members[index];
}
};
class CallStack {
public:
std::vector<ActivationRecord> records;
void push(ActivationRecord& ar) {
records.push_back(ar);
}
void pop() {
records.pop_back();
}
ActivationRecord& peek() {
return records.back();
}
};
153 changes: 153 additions & 0 deletions Interpreter/SymbolTable.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
#pragma once
#include <string>
#include <iostream>
#include <map>
#include "../Parser/astnodes.h"
#include "./Symbols.h"
class ScopedSymbolTable {
private:
std::string scope_name;
public:
int scope_level;
ScopedSymbolTable* enclosingScope = NULL;
std::map<std::string, Symbol*> symbols;
ScopedSymbolTable(std::string name, int level) {
define(new BuiltinTypeSymbol("int"));
define(new BuiltinTypeSymbol("real"));
define(new BuiltinTypeSymbol("string"));
scope_name = name;
scope_level = level;
}
void define(Symbol* symbol) {
// std::// cout << "Define: " << symbol->print() << std::endl;
symbols[symbol->name] = symbol;
}
Symbol* lookup(std::string name) {
// std::// cout << "Lookup: " << name << "\n";
if (symbols.count(name)) {
return symbols[name];
}
else {
if (enclosingScope != NULL) return enclosingScope->lookup(name);
else return new Symbol();
}
}
std::string print() {
std::string rep("");
rep += "SCOPE (SCOPED SYMBOL TABLE)\n==================\n";
rep += "Scope name: " + scope_name + "\n";
rep += "Scope level: " + std::to_string(scope_level) + "\n";
rep += "Contents:\n...................\n";
for (auto pair : symbols) {
rep += pair.first + ": " + pair.second->print() + "\n";
}
rep += "====================\n";
return rep;
}
};
class SymbolTableBuilder {
public:
ScopedSymbolTable symtab;
ScopedSymbolTable& currentScope;
std::map<std::string, std::string> types;
SymbolTableBuilder(std::string name, int level) : symtab("global", 1), currentScope(symtab) {
}
void visit(AstNode* node) {
if (node->print() == "Program") visit_Program(*static_cast<Program*>(node));
else if (node->print() == "FunctionDecl") visit_ProcedureDecl(*static_cast<FunctionDecl*>(node));
else if (node->print() == "FunctionCall") visit_FunctionCall(*static_cast<FunctionCall*>(node));
else if (node->print() == "Block") visit_Block(*static_cast<Block*>(node));
else if (node->print() == "UnOp") visit_UnOp(*static_cast<UnOp*>(node));
else if (node->print() == "Var") visit_Var(*static_cast<Var*>(node));
else if (node->print() == "BinOp") return visit_BinOp(*static_cast<BinOp*>(node));
else if (node->print() == "Assign") visit_Assign(*static_cast<class Assign*>(node));
}
void visit_FunctionCall(FunctionCall& functionCall) {
if (functionCall.params.size() != static_cast<ProcedureSymbol*>(symtab.lookup(functionCall.proc_name))->params.size()) {
std::string error("Function call parameters do not match function parameters.");
throw error;
}
for (AstNode* param : functionCall.params) {
visit(param);
}
ProcedureSymbol procSymbol = *static_cast<ProcedureSymbol*>(symtab.lookup(functionCall.proc_name));
functionCall.procSymbol = procSymbol;
}
void visit_Program(Program program) {
// // cout << "Enter scope: GLOBAL\n";
ScopedSymbolTable globalScope("global", 1);
currentScope = globalScope;
visit_Block(program.block);
// // cout << currentScope.print();
// // cout << "Leave scope: GLOBAL\n";
}
void visit_ProcedureDecl(FunctionDecl proc) {
ProcedureSymbol* proc_symbol = new ProcedureSymbol(proc.name);
currentScope.define(proc_symbol);
// // cout << "Enter scope: " << proc.name << endl;
ScopedSymbolTable proc_scope(proc.name, currentScope.scope_level + 1);
ScopedSymbolTable* enclosing = new ScopedSymbolTable(currentScope);
proc_scope.enclosingScope = enclosing;
currentScope = proc_scope;
for (VarDecl param : proc.params) {
BuiltinTypeSymbol* type = static_cast<BuiltinTypeSymbol*>(currentScope.lookup(param.type.type));
std::string param_name = param.var.value;
Symbol* var = new VarSymbol(param_name, type);
currentScope.define(var);
VarSymbol var_symbol(param_name, type);
proc_symbol->params.push_back(var_symbol);
types[param_name] = param.type.type;
}
visit_Block(proc.block);
// // cout << currentScope.print();
currentScope = *proc_scope.enclosingScope;
proc_symbol->blockAst = *new Block(proc.block);
}
void visit_Block(Block block) {
for (VarDecl decl : block.declarations) {
visit_VarDecl(decl);
}
for (FunctionDecl* decl : block.procedures) {
visit(decl);
}
for (AstNode* node : block.children) {
visit(node);
}
}
void visit_UnOp(UnOp unOp) {
visit(unOp.expr);
}
void visit_BinOp(BinOp binOp) {
visit(binOp.left);
visit(binOp.right);
}
void visit_Assign(class Assign assign) {
std::string var_name = assign.var.value;
Symbol* var_symbol = currentScope.lookup(var_name);
if (var_symbol->name == "") {
std::string error = "Error: variable not defined: " + var_name;
throw error;
}
visit(assign.right);
}
void visit_Var(Var var) {
std::string var_name = var.value;
Symbol* var_symbol = currentScope.lookup(var_name);
if (var_symbol->name == "") {
std::string error = "Error: variable not defined: " + var_name;
throw error;
}
}
void visit_VarDecl(VarDecl varDecl) {
std::string type_name = varDecl.type.type;
BuiltinTypeSymbol* type_symbol = static_cast<BuiltinTypeSymbol*>(currentScope.lookup(type_name));
std::string var_name = varDecl.var.value;
if (currentScope.lookup(var_name)->name != "") {
std::string error("Multiple definition of variable " + var_name);
throw error;
}
VarSymbol* var = new VarSymbol(var_name, type_symbol);
currentScope.define(var);
types[var_name] = type_name;
}
};
99 changes: 0 additions & 99 deletions Interpreter/Symbols.h
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
#pragma once
#include <string>
#include <iostream>
#include <map>
#include "../Parser/astnodes.h"
class Symbol
{
private:
Expand Down Expand Up @@ -34,99 +31,3 @@ class VarSymbol : public Symbol
private:

};
class ScopedSymbolTable {
private:
std::string scope_name;
int scope_level;
public:
std::map<std::string, Symbol*> symbols;
ScopedSymbolTable(std::string name, int level) {
define(new BuiltinTypeSymbol("int"));
define(new BuiltinTypeSymbol("real"));
define(new BuiltinTypeSymbol("string"));
scope_name = name;
scope_level = level;
}
void define(Symbol* symbol) {
// std::cout << "Define: " << symbol->print() << std::endl;
symbols[symbol->name] = symbol;
}
Symbol* lookup(std::string name) {
// std::cout << "Lookup: " << name << "\n";
if (symbols.count(name)) {
return symbols[name];
}
else {
return new Symbol();
}
}
std::string print() {
std::string rep("");
rep += "SCOPE (SCOPED SYMBOL TABLE)\n==================\n";
rep += "Scope name: " + scope_name + "\n";
rep += "Scope level: " + std::to_string(scope_level) + "\n";
rep += "Contents:\n...................\n";
for (auto pair : symbols) {
rep += pair.first + ": " + pair.second->print() + "\n";
}
rep += "====================\n";
return rep;
}
};
class SymbolTableBuilder {
public:
ScopedSymbolTable symtab;
SymbolTableBuilder(std::string name, int level) : symtab(name, level) {

}
void visit(AstNode * node) {
if (node->print() == "Block") visit_Block(*static_cast<Block*>(node));
else if (node->print() == "UnOp") visit_UnOp(*static_cast<UnOp*>(node));
else if (node->print() == "Var") visit_Var(*static_cast<Var*>(node));
else if (node->print() == "BinOp") return visit_BinOp(*static_cast<BinOp*>(node));
else if (node->print() == "Assign") visit_Assign(*static_cast<class Assign*>(node));
}
void visit_Block(Block block) {
for (VarDecl decl : block.declarations) {
visit_VarDecl(decl);
}
for (AstNode* node : block.children) {
visit(node);
}
}
void visit_UnOp(UnOp unOp) {
visit(unOp.expr);
}
void visit_BinOp(BinOp binOp) {
visit(binOp.left);
visit(binOp.right);
}
void visit_Assign(class Assign assign) {
std::string var_name = assign.var.value;
Symbol* var_symbol = symtab.lookup(var_name);
if (var_symbol->name == "") {
std::string error = "Error: variable not defined: " + var_name;
throw error;
}
visit(assign.right);
}
void visit_Var(Var var) {
std::string var_name = var.value;
Symbol* var_symbol = symtab.lookup(var_name);
if (var_symbol->name == "") {
std::string error = "Error: variable not defined: " + var_name;
throw error;
}
}
void visit_VarDecl(VarDecl varDecl) {
std::string type_name = varDecl.type.type;
BuiltinTypeSymbol* type_symbol = static_cast<BuiltinTypeSymbol*>(symtab.lookup(type_name));
std::string var_name = varDecl.var.value;
if (symtab.lookup(var_name)->name != "") {
std::string error("Multiple definition of variable " + var_name);
throw error;
}
VarSymbol* var = new VarSymbol(var_name, type_symbol);
symtab.define(var);
}
};
Loading

0 comments on commit a8a9257

Please sign in to comment.