Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Merge pull request #444 from galchinsky/replStreamParsing

Extract  parser.hpp from clay.hpp. Multi-line input for repl
  • Loading branch information...
commit 53afb33339c835c26059be4cc700bfffe87f78f1 2 parents abcbba6 + 4ce8ec5
@jckarter authored
View
6 compiler/clay.cpp
@@ -1096,11 +1096,11 @@ int main2(int argc, char **argv, char const* const* envp) {
vector<string> sourceFiles;
if (!clayScript.empty()) {
clayScriptSource = clayScriptImports + "main() {\n" + clayScript + "}";
- m = loadProgramSource("-e", clayScriptSource, verbose);
+ m = loadProgramSource("-e", clayScriptSource, verbose, repl);
} else if (generateDeps)
- m = loadProgram(clayFile, &sourceFiles, verbose);
+ m = loadProgram(clayFile, &sourceFiles, verbose, repl);
else
- m = loadProgram(clayFile, NULL, verbose);
+ m = loadProgram(clayFile, NULL, verbose, repl);
loadTimer.stop();
compileTimer.start();
View
24 compiler/clay.hpp
@@ -2481,30 +2481,6 @@ struct MultiPValue : public Object {
//
-// parser module
-//
-
-
-enum ParserFlags
-{
- NoParserFlags = 0,
- ParserKeepDocumentation = 1
-};
-
-ModulePtr parse(llvm::StringRef moduleName, SourcePtr source, ParserFlags flags = NoParserFlags);
-ExprPtr parseExpr(SourcePtr source, int offset, int length);
-ExprListPtr parseExprList(SourcePtr source, int offset, int length);
-void parseStatements(SourcePtr source, int offset, int length,
- vector<StatementPtr> &statements);
-void parseTopLevelItems(SourcePtr source, int offset, int length,
- vector<TopLevelItemPtr> &topLevels, Module *);
-void parseInteractive(SourcePtr source, int offset, int length,
- vector<TopLevelItemPtr>& toplevels,
- vector<ImportPtr>& imports,
- vector<StatementPtr>& stmts);
-
-
-//
// printer module
//
View
1  compiler/claydoc.cpp
@@ -1,4 +1,5 @@
#include "claydoc.hpp"
+#include "parser.hpp"
#include <sstream>
#include <string>
View
2  compiler/codegen.cpp
@@ -11,7 +11,7 @@
#include "literals.hpp"
#include "desugar.hpp"
#include "constructors.hpp"
-
+#include "parser.hpp"
#pragma clang diagnostic ignored "-Wcovered-switch-default"
View
2  compiler/desugar.cpp
@@ -3,7 +3,7 @@
#include "evaluator.hpp"
#include "analyzer.hpp"
#include "desugar.hpp"
-
+#include "parser.hpp"
namespace clay {
View
164 compiler/interactive.cpp
@@ -1,8 +1,10 @@
#include "clay.hpp"
#include "lexer.hpp"
+#include "parser.hpp"
#include "codegen.hpp"
#include "error.hpp"
#include "loader.hpp"
+#include "invoketables.hpp"
#include <setjmp.h>
#include <signal.h>
@@ -10,7 +12,7 @@
namespace clay {
- using std::ostringstream;
+ typedef llvm::SmallString<16U> Str;
const char* replAnonymousFunctionName = "__replAnonymousFunction__";
@@ -21,6 +23,8 @@ namespace clay {
static bool printAST = false;
+ static void eval(llvm::StringRef code);
+
string newFunctionName()
{
static int funNum = 0;
@@ -41,29 +45,109 @@ namespace clay {
return s.substr(i, s.length());
}
+ static vector<Token> addTokens() {
+ char buf[255];
+ string line = fgets(buf, 255, stdin);
+ line = stripSpaces(line);
+ SourcePtr source = new Source(line, 0);
+ vector<Token> tokens;
+ tokenize(source, 0, line.length(), tokens);
+ return tokens;
+ }
+
+ static void cmdGlobals(const vector<Token>& tokens) {
+ ModulePtr m;
+ if (tokens.size() == 1) {
+ m = module;
+ } else if (tokens.size() == 2) {
+ m = globalModules[tokens[1].str];
+ } else {
+ llvm::errs() << ":globals [module name]\n";
+ return;
+ }
+
+ string buf;
+ llvm::raw_string_ostream code(buf);
+
+ llvm::StringMap<ObjectPtr>::const_iterator g = m->globals.begin();
+ for (; g != m->globals.end(); ++g) {
+ if (g->second->objKind == GLOBAL_VARIABLE) {
+ IdentifierPtr name = ((GlobalVariable*)g->second.ptr())->name;
+ code << "println(\"" << name->str << " : \", "
+ << "Type(" << name->str << "), \" : \", "
+ << name->str <<");\n";
+ }
+ }
+ code.flush();
+ eval(buf);
+ }
+
+ static void cmdModules(const vector<Token>& tokens) {
+ if (tokens.size() != 1) {
+ llvm::errs() << "Warning: command parameters are ignored\n";
+ }
+ llvm::StringMap<ModulePtr>::const_iterator iter = globalModules.begin();
+ for (; iter != globalModules.end(); ++iter) {
+ llvm::errs() << iter->getKey() << "\n";
+ }
+ }
+
+ static void cmdOverloads(const vector<Token>& tokens) {
+ for (size_t i = 1; i < tokens.size(); ++i) {
+ if (tokens[i].tokenKind == T_IDENTIFIER) {
+ Str identStr = tokens[i].str;
+
+ ObjectPtr obj = lookupPrivate(module, Identifier::get(identStr));
+ if (obj == NULL || obj->objKind != PROCEDURE) {
+ llvm::errs() << identStr << " is not a procedure name\n";
+ continue;
+ }
+
+ vector<InvokeSet*> sets = lookupInvokeSets(obj.ptr());
+ for (size_t k = 0; k < sets.size(); ++k) {
+ llvm::errs() << " ";
+ for (size_t l = 0; l < sets[k]->argsKey.size(); ++l) {
+ llvm::errs() << sets[k]->argsKey[l] << " : ";
+ }
+ llvm::errs() << "\n";
+ }
+ }
+ }
+ }
+
+ static void cmdPrint(const vector<Token>& tokens) {
+ for (size_t i = 1; i < tokens.size(); ++i) {
+ if (tokens[i].tokenKind == T_IDENTIFIER) {
+ Str identifier = tokens[i].str;
+ llvm::StringMap<ImportSet>::const_iterator iter = module->allSymbols.find(identifier);
+ if (iter == module->allSymbols.end()) {
+ llvm::errs() << "Can't find identifier " << identifier.c_str();
+ } else {
+ for (size_t i = 0; i < iter->second.size(); ++i) {
+ llvm::errs() << iter->second[i] << "\n";
+ }
+ }
+ }
+ }
+ }
+
static void replCommand(string const& line)
{
- typedef llvm::SmallString<16U> Str;
SourcePtr source = new Source(line, 0);
vector<Token> tokens;
+ //TODO: don't use compiler's tokenizer
tokenize(source, 0, line.length(), tokens);
Str cmd = tokens[0].str;
if (cmd == "q") {
exit(0);
+ } else if (cmd == "globals") {
+ cmdGlobals(tokens);
+ } else if (cmd == "modules") {
+ cmdModules(tokens);
+ } else if (cmd == "overloads") {
+ cmdOverloads(tokens);
} else if (cmd == "print") {
- for (size_t i = 1; i < tokens.size(); ++i) {
- if (tokens[i].tokenKind == T_IDENTIFIER) {
- Str identifier = tokens[i].str;
- llvm::StringMap<ImportSet>::const_iterator iter = module->allSymbols.find(identifier);
- if (iter == module->allSymbols.end()) {
- llvm::errs() << "Can't find identifier " << identifier.c_str();
- } else {
- for (size_t i = 0; i < iter->second.size(); ++i) {
- llvm::errs() << iter->second[i] << "\n";
- }
- }
- }
- }
+ cmdPrint(tokens);
} else if (cmd == "ast_on") {
printAST = true;
} else if (cmd == "ast_off") {
@@ -76,7 +160,7 @@ namespace clay {
}
}
- static void loadImports(llvm::ArrayRef<ImportPtr> imports)
+ static void loadImports(llvm::ArrayRef<ImportPtr> imports)
{
for (size_t i = 0; i < imports.size(); ++i) {
module->imports.push_back(imports[i]);
@@ -89,7 +173,7 @@ namespace clay {
}
}
- static void jitTopLevel(llvm::ArrayRef<TopLevelItemPtr> toplevels)
+ static void jitTopLevel(llvm::ArrayRef<TopLevelItemPtr> toplevels)
{
if (toplevels.empty()) {
return;
@@ -102,7 +186,7 @@ namespace clay {
addGlobals(module, toplevels);
}
- static void jitStatements(llvm::ArrayRef<StatementPtr> statements)
+ static void jitStatements(llvm::ArrayRef<StatementPtr> statements)
{
if (statements.empty()) {
return;
@@ -149,6 +233,31 @@ namespace clay {
engine->runFunction(entryProc->llvmFunc, std::vector<llvm::GenericValue>());
}
+ static void jitAndPrintExpr(ExprPtr expr) {
+ //expr -> println(expr);
+ NameRefPtr println = new NameRef(Identifier::get("println"));
+ ExprPtr call = new Call(println.ptr(), new ExprList(expr));
+ ExprStatementPtr callStmt = new ExprStatement(call);
+ jitStatements(vector<StatementPtr>(1, callStmt.ptr()));
+ }
+
+ static void eval(llvm::StringRef line) {
+ SourcePtr source = new Source(line, 0);
+ try {
+ ReplItem x = parseInteractive(source, 0, source->size());
+ if (x.isExprSet) {
+ jitAndPrintExpr(x.expr);
+ } else {
+ loadImports(x.imports);
+ jitTopLevel(x.toplevels);
+ jitStatements(x.stmts);
+ }
+ }
+ catch (CompilerError) {
+ return;
+ }
+ }
+
static void interactiveLoop()
{
setjmp(recovery);
@@ -162,19 +271,7 @@ namespace clay {
if (line[0] == ':') {
replCommand(line.substr(1, line.size() - 1));
} else {
- SourcePtr source = new Source(line, 0);
- vector<StatementPtr> stmts;
- vector<TopLevelItemPtr> toplevels;
- vector<ImportPtr> imports;
- try {
- parseInteractive(source, 0, source->size(), toplevels, imports, stmts);
- loadImports(imports);
- jitTopLevel(toplevels);
- jitStatements(stmts);
- }
- catch (CompilerError) {
- continue;
- }
+ eval(line);
}
}
engine->runStaticConstructorsDestructors(true);
@@ -197,6 +294,9 @@ namespace clay {
llvm::errs() << "Clay interpreter\n";
llvm::errs() << ":q to exit\n";
llvm::errs() << ":print {identifier} to print an identifier\n";
+ llvm::errs() << ":modules to list global modules\n";
+ llvm::errs() << ":globals to list globals\n";
+ llvm::errs() << "In multi-line mode empty line to exit\n";
llvm::EngineBuilder eb(llvmModule);
llvm::TargetOptions targetOptions;
@@ -205,6 +305,8 @@ namespace clay {
engine = eb.create();
engine->runStaticConstructorsDestructors(false);
+ setAddTokens(&addTokens);
+
interactiveLoop();
}
View
13 compiler/invoketables.cpp
@@ -171,6 +171,19 @@ InvokeSet* lookupInvokeSet(ObjectPtr callable,
return invokeSet;
}
+vector<InvokeSet*> lookupInvokeSets(ObjectPtr callable) {
+ assert(invokeTablesInitialized);
+ vector<InvokeSet*> r;
+ for (size_t i = 0; i < invokeTable.size(); ++i) {
+ for (size_t j = 0; j < invokeTable[i].size(); ++j) {
+ InvokeSet* set = invokeTable[i][j];
+ if (objectEquals(set->callable, callable)) {
+ r.push_back(set);
+ }
+ }
+ }
+ return r;
+}
//
View
1  compiler/invoketables.hpp
@@ -105,6 +105,7 @@ struct MatchFailureError {
InvokeSet *lookupInvokeSet(ObjectPtr callable,
llvm::ArrayRef<TypePtr> argsKey);
+vector<InvokeSet*> lookupInvokeSets(ObjectPtr callable);
InvokeEntry* lookupInvokeEntry(ObjectPtr callable,
llvm::ArrayRef<TypePtr> argsKey,
llvm::ArrayRef<ValueTempness> argsTempness,
View
27 compiler/loader.cpp
@@ -5,7 +5,7 @@
#include "codegen.hpp"
#include "evaluator.hpp"
#include "constructors.hpp"
-
+#include "parser.hpp"
#pragma clang diagnostic ignored "-Wcovered-switch-default"
@@ -396,15 +396,24 @@ static void loadDependents(ModulePtr m, vector<string> *sourceFiles, bool verbos
}
}
-static ModulePtr loadPrelude(vector<string> *sourceFiles, bool verbose) {
- DottedNamePtr dottedName = new DottedName();
- dottedName->parts.push_back(Identifier::get("prelude"));
- return loadModuleByName(dottedName, sourceFiles, verbose);
+static ModulePtr loadPrelude(vector<string> *sourceFiles, bool verbose, bool repl) {
+ if (!repl) {
+ DottedNamePtr dottedName = new DottedName();
+ dottedName->parts.push_back(Identifier::get("prelude"));
+ return loadModuleByName(dottedName, sourceFiles, verbose);
+ } else {
+ DottedNamePtr dottedName = new DottedName();
+ dottedName->parts.push_back(Identifier::get("prelude"));
+ dottedName->parts.push_back(Identifier::get("repl"));
+ ModulePtr m = loadModuleByName(dottedName, sourceFiles, verbose);
+ globalModules["prelude"] = m;
+ return m;
+ }
}
-ModulePtr loadProgram(llvm::StringRef fileName, vector<string> *sourceFiles, bool verbose) {
+ModulePtr loadProgram(llvm::StringRef fileName, vector<string> *sourceFiles, bool verbose, bool repl) {
globalMainModule = parse("", loadFile(fileName, sourceFiles));
- ModulePtr prelude = loadPrelude(sourceFiles, verbose);
+ ModulePtr prelude = loadPrelude(sourceFiles, verbose, repl);
loadDependents(globalMainModule, sourceFiles, verbose);
installGlobals(globalMainModule);
initModule(prelude);
@@ -412,7 +421,7 @@ ModulePtr loadProgram(llvm::StringRef fileName, vector<string> *sourceFiles, boo
return globalMainModule;
}
-ModulePtr loadProgramSource(llvm::StringRef name, llvm::StringRef source, bool verbose) {
+ModulePtr loadProgramSource(llvm::StringRef name, llvm::StringRef source, bool verbose, bool repl) {
SourcePtr mainSource = new Source(name,
llvm::MemoryBuffer::getMemBufferCopy(source));
if (llvmDIBuilder != NULL) {
@@ -423,7 +432,7 @@ ModulePtr loadProgramSource(llvm::StringRef name, llvm::StringRef source, bool v
globalMainModule = parse("", mainSource);
// Don't keep track of source files for -e script
- ModulePtr prelude = loadPrelude(NULL, verbose);
+ ModulePtr prelude = loadPrelude(NULL, verbose, repl);
loadDependents(globalMainModule, NULL, verbose);
installGlobals(globalMainModule);
initModule(prelude);
View
4 compiler/loader.hpp
@@ -16,8 +16,8 @@ void getProcedureMonoTypes(ProcedureMono &mono, EnvPtr env,
void initLoader();
void setSearchPath(const llvm::ArrayRef<PathString> path);
-ModulePtr loadProgram(llvm::StringRef fileName, vector<string> *sourceFiles, bool verbose);
-ModulePtr loadProgramSource(llvm::StringRef name, llvm::StringRef source, bool verbose);
+ModulePtr loadProgram(llvm::StringRef fileName, vector<string> *sourceFiles, bool verbose, bool repl);
+ModulePtr loadProgramSource(llvm::StringRef name, llvm::StringRef source, bool verbose, bool repl);
ModulePtr loadedModule(llvm::StringRef module);
ModulePtr preludeModule();
ModulePtr primitivesModule();
View
62 compiler/parser.cpp
@@ -1,5 +1,5 @@
#include "clay.hpp"
-#include "lexer.hpp"
+#include "parser.hpp"
namespace clay {
@@ -11,9 +11,28 @@ static int position;
static int maxPosition;
static bool parserOptionKeepDocumentation = false;
+static AddTokensCallback addTokens = NULL;
+
+void setAddTokens(AddTokensCallback f) {
+ addTokens = f;
+}
+
+static bool inRepl = false;
+
static bool next(Token *&x) {
- if (position == (int)tokens->size())
- return false;
+ if (position == (int)tokens->size()) {
+ if (inRepl) {
+ assert(addTokens != NULL);
+ vector<Token> toks = addTokens();
+ if (toks.size() == 0) {
+ inRepl = false;
+ return false;
+ }
+ tokens->insert(tokens->end(), toks.begin(), toks.end());
+ } else {
+ return false;
+ }
+ }
x = &(*tokens)[position];
if (position > maxPosition)
maxPosition = position;
@@ -3091,31 +3110,42 @@ static bool module(llvm::StringRef moduleName, ModulePtr &x) {
// REPL
//
-struct REPLitem {
- vector<TopLevelItemPtr> toplevels;
- vector<ImportPtr> imports;
- vector<StatementPtr> stmts;
-};
+static bool replItems(ReplItem& x, bool = false) {
+ inRepl = false;
+ int p = save();
+ if (expression(x.expr) && position == tokens->size()) {
+ x.isExprSet = true;
+ return true;
+ }
+ restore(p);
-static bool replItems(REPLitem& x, bool = false) {
+ inRepl = true;
x.toplevels.clear();
x.imports.clear();
x.stmts.clear();
ImportPtr importItem;
StatementPtr stmtItem;
+
while (true) {
+ if (position == (int)tokens->size()) {
+ break;
+ }
+
int p = save();
+
if (!topLevelItem(x.toplevels, NULL)) {
restore(p);
} else {
continue;
}
+
if (!import(importItem)) {
restore(p);
} else {
x.imports.push_back(importItem);
continue;
}
+
if (!blockItem(stmtItem)) {
restore(p);
break;
@@ -3123,6 +3153,9 @@ static bool replItems(REPLitem& x, bool = false) {
x.stmts.push_back(stmtItem);
}
}
+
+ x.isExprSet = false;
+
return true;
}
@@ -3217,16 +3250,11 @@ void parseTopLevelItems(SourcePtr source, int offset, int length,
// parseInteractive
//
-void parseInteractive(SourcePtr source, int offset, int length,
- vector<TopLevelItemPtr>& toplevels,
- vector<ImportPtr>& imports,
- vector<StatementPtr>& stmts)
+ReplItem parseInteractive(SourcePtr source, int offset, int length)
{
- REPLitem x;
+ ReplItem x;
applyParser(source, offset, length, replItems, false, x);
- toplevels = x.toplevels;
- imports = x.imports;
- stmts = x.stmts;
+ return x;
}
}
View
37 compiler/parser.hpp
@@ -0,0 +1,37 @@
+#ifndef __PARSER_HPP
+#define __PARSER_HPP
+
+#include "clay.hpp"
+#include "lexer.hpp"
+
+namespace clay {
+
+enum ParserFlags
+{
+ NoParserFlags = 0,
+ ParserKeepDocumentation = 1
+};
+
+struct ReplItem {
+ bool isExprSet;
+ ExprPtr expr;
+ vector<TopLevelItemPtr> toplevels;
+ vector<ImportPtr> imports;
+ vector<StatementPtr> stmts;
+};
+
+ModulePtr parse(llvm::StringRef moduleName, SourcePtr source, ParserFlags flags = NoParserFlags);
+ExprPtr parseExpr(SourcePtr source, int offset, int length);
+ExprListPtr parseExprList(SourcePtr source, int offset, int length);
+void parseStatements(SourcePtr source, int offset, int length,
+ vector<StatementPtr> &statements);
+void parseTopLevelItems(SourcePtr source, int offset, int length,
+ vector<TopLevelItemPtr> &topLevels, Module *);
+ReplItem parseInteractive(SourcePtr source, int offset, int length);
+
+typedef vector<Token>(*AddTokensCallback)();
+void setAddTokens(AddTokensCallback f);
+
+}
+
+#endif // __PARSER_HPP
View
2  lib-clay/prelude/repl/repl.clay
@@ -0,0 +1,2 @@
+public import prelude.*;
+public import printer.*;
Please sign in to comment.
Something went wrong with that request. Please try again.