aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/cps.cpp2
-rw-r--r--src/lex.cpp26
-rw-r--r--src/parse.cpp69
-rw-r--r--src/pprint.cpp4
-rw-r--r--src/repl.cpp12
-rw-r--r--src/tuplr.cpp2
-rw-r--r--src/tuplr.hpp98
7 files changed, 99 insertions, 114 deletions
diff --git a/src/cps.cpp b/src/cps.cpp
index 75b771f..b8b6b62 100644
--- a/src/cps.cpp
+++ b/src/cps.cpp
@@ -33,7 +33,7 @@ AST::cps(TEnv& tenv, AST* cont)
AST*
AFn::cps(TEnv& tenv, AST* cont)
{
- ATuple* copyProt = new ATuple(prot()->loc, *prot());
+ ATuple* copyProt = new ATuple(*prot());
ASymbol* contArg = tenv.penv.gensym("_k");
copyProt->push_back(contArg);
AFn* copy = tup<AFn>(loc, tenv.penv.sym("fn"), copyProt, 0);
diff --git a/src/lex.cpp b/src/lex.cpp
index bfdd9c1..b5c89e9 100644
--- a/src/lex.cpp
+++ b/src/lex.cpp
@@ -16,7 +16,7 @@
*/
/** @file
- * @brief Lexing (build a SExp from a string)
+ * @brief Lexing (build an unparsed textual AST from a string)
*/
#include <stack>
@@ -36,19 +36,19 @@ readChar(Cursor& cur, istream& in)
}
/// Read an expression from @a in
-SExp
+AST*
readExpression(Cursor& cur, istream& in)
{
-#define PUSH(s, t) { if (t != "") { s.top().push_back(SExp(loc, new AString(loc, t))); t = ""; } }
-#define YIELD(s, t) { if (s.empty()) { return SExp(loc, new AString(loc, t)); } else PUSH(s, t) }
- stack<SExp> stk;
- string tok;
- Cursor loc; // start of tok
+#define PUSH(s, t) { if (t != "") { s.top()->push_back(new AString(loc, t)); t = ""; } }
+#define YIELD(s, t) { if (s.empty()) { return new AString(loc, t); } else PUSH(s, t) }
+ stack<ATuple*> stk;
+ string tok;
+ Cursor loc; // start of tok
while (int c = readChar(cur, in)) {
switch (c) {
case EOF:
THROW_IF(!stk.empty(), cur, "unexpected end of file")
- return SExp(cur);
+ return new ATuple(cur);
case ';':
while ((c = readChar(cur, in)) != '\n') {}
case '\n': case ' ': case '\t':
@@ -60,7 +60,7 @@ readExpression(Cursor& cur, istream& in)
YIELD(stk, tok + '"');
break;
case '(':
- stk.push(SExp(cur));
+ stk.push(new ATuple(cur));
break;
case ')':
switch (stk.size()) {
@@ -71,9 +71,9 @@ readExpression(Cursor& cur, istream& in)
return stk.top();
default:
PUSH(stk, tok);
- SExp l = stk.top();
+ ATuple* l = stk.top();
stk.pop();
- stk.top().push_back(l);
+ stk.top()->push_back(l);
}
break;
case '#':
@@ -87,9 +87,9 @@ readExpression(Cursor& cur, istream& in)
}
}
switch (stk.size()) {
- case 0: return SExp(loc, new AString(loc, tok));
+ case 0: return new AString(loc, tok);
case 1: return stk.top();
default: throw Error(cur, "missing `)'");
}
- return SExp(cur);
+ return new ATuple(cur);
}
diff --git a/src/parse.cpp b/src/parse.cpp
index a065e64..1f16bfe 100644
--- a/src/parse.cpp
+++ b/src/parse.cpp
@@ -16,7 +16,7 @@
*/
/** @file
- * @brief Parsing (build an AST from a SExp)
+ * @brief Parsing (build a code AST from a textual AST)
*/
#include "tuplr.hpp"
@@ -28,31 +28,34 @@ using namespace std;
* Macro Functions *
***************************************************************************/
-inline SExp
-macDef(PEnv& penv, const SExp& exp)
+inline AST*
+macDef(PEnv& penv, const AST* exp)
{
- SExp::const_iterator i = exp.begin();
- THROW_IF(i == exp.end(), exp.loc, "Unexpected end of `def' macro call");
- const SExp& name = *(++i);
- THROW_IF(i == exp.end(), name.loc, "Unexpected end of `def' macro call");
- if (name.type == SExp::ATOM) {
- return exp;
+ const ATuple* tup = exp->to<const ATuple*>();
+ ATuple::const_iterator i = tup->begin();
+ THROW_IF(i == tup->end(), tup->loc, "Unexpected end of `def' macro call");
+ const AST* name = *(++i);
+ THROW_IF(i == tup->end(), name->loc, "Unexpected end of `def' macro call");
+ if (name->to<const AString*>()) {
+ return const_cast<AST*>(exp);
} else {
+ const ATuple* pat = name->to<const ATuple*>();
+ name = pat->at(0);
// (def (f x) y) => (def f (fn (x) y))
- SExp argsExp(exp.loc);
- SExp::const_iterator j = name.begin();
- for (++j; j != name.end(); ++j)
- argsExp.push_back(*j);
- const SExp& body = *(++i);
- SExp fnExp(body.loc);
- fnExp.push_back(SExp(body.loc, new AString(body.loc, "fn")));
- fnExp.push_back(argsExp);
- for (; i != exp.end(); ++i)
- fnExp.push_back(*i);
- SExp ret(exp.loc);
- ret.push_back(exp.front());
- ret.push_back(name.front());
- ret.push_back(fnExp);
+ ATuple* argsExp = new ATuple(exp->loc);
+ ATuple::const_iterator j = pat->begin();
+ for (++j; j != pat->end(); ++j)
+ argsExp->push_back(*j);
+ const AST* body = *(++i);
+ ATuple* fnExp = new ATuple(body->loc);
+ fnExp->push_back(new AString(exp->loc, "fn"));
+ fnExp->push_back(argsExp);
+ for (; i != tup->end(); ++i)
+ fnExp->push_back(*i);
+ ATuple* ret = new ATuple(exp->loc);
+ ret->push_back(const_cast<AST*>(tup->front()));
+ ret->push_back(const_cast<AST*>(name));
+ ret->push_back(fnExp);
return ret;
}
}
@@ -64,25 +67,27 @@ macDef(PEnv& penv, const SExp& exp)
template<typename C>
inline AST*
-parseCall(PEnv& penv, const SExp& exp, void* arg)
+parseCall(PEnv& penv, const AST* exp, void* arg)
{
- return new C(exp, penv.parseTuple(exp));
+ return new C(penv.parseTuple(exp->to<const ATuple*>()));
}
template<typename T>
inline AST*
-parseLiteral(PEnv& penv, const SExp& exp, void* arg)
+parseLiteral(PEnv& penv, const AST* exp, void* arg)
{
- return new ALiteral<T>(*reinterpret_cast<T*>(arg), exp.loc);
+ return new ALiteral<T>(*reinterpret_cast<T*>(arg), exp->loc);
}
inline AST*
-parseFn(PEnv& penv, const SExp& exp, void* arg)
+parseFn(PEnv& penv, const AST* exp, void* arg)
{
- SExp::const_iterator a = exp.begin();
- THROW_IF(++a == exp.end(), exp.loc, "Unexpected end of `fn' form");
- AFn* ret = tup<AFn>(exp.loc, penv.sym("fn"), new ATuple(penv.parseTuple(*a++)), 0);
- while (a != exp.end())
+ const ATuple* texp = exp->to<const ATuple*>();
+ ATuple::const_iterator a = texp->begin();
+ THROW_IF(++a == texp->end(), exp->loc, "Unexpected end of `fn' form");
+ ATuple* prot = penv.parseTuple((*a++)->to<const ATuple*>());
+ AFn* ret = tup<AFn>(exp->loc, penv.sym("fn"), prot, 0);
+ while (a != texp->end())
ret->push_back(penv.parse(*a++));
return ret;
}
diff --git a/src/pprint.cpp b/src/pprint.cpp
index cb507b1..ddbd403 100644
--- a/src/pprint.cpp
+++ b/src/pprint.cpp
@@ -36,6 +36,10 @@ operator<<(ostream& out, const AST* ast)
if (blit)
return out << (blit->val ? "#t" : "#f");
+ const AString* str = ast->to<const AString*>();
+ if (str)
+ return out << *str;
+
const ASymbol* sym = ast->to<const ASymbol*>();
if (sym)
return out << sym->cppstr;
diff --git a/src/repl.cpp b/src/repl.cpp
index 1ec1834..bca6037 100644
--- a/src/repl.cpp
+++ b/src/repl.cpp
@@ -32,12 +32,12 @@ eval(CEnv& cenv, const string& name, istream& is)
{
AST* result = NULL;
AType* resultType = NULL;
- list< pair<SExp, AST*> > exprs;
+ list< pair<AST*, AST*> > exprs;
Cursor cursor(name);
try {
while (true) {
- SExp exp = readExpression(cursor, is);
- if (exp.type == SExp::LIST && exp.empty())
+ AST* exp = readExpression(cursor, is);
+ if (exp->to<ATuple*>() && exp->to<ATuple*>()->empty())
break;
result = cenv.penv.parse(exp); // Parse input
@@ -71,7 +71,7 @@ eval(CEnv& cenv, const string& name, istream& is)
CFunction f = cenv.engine()->startFunction(cenv, "main", resultType, ATuple(cursor));
// Compile all expressions into it
- for (list< pair<SExp, AST*> >::const_iterator i = exprs.begin(); i != exprs.end(); ++i)
+ for (list< pair<AST*, AST*> >::const_iterator i = exprs.begin(); i != exprs.end(); ++i)
val = cenv.compile(i->second);
// Finish and call it
@@ -102,8 +102,8 @@ repl(CEnv& cenv)
Cursor cursor("(stdin)");
try {
- SExp exp = readExpression(cursor, std::cin);
- if (exp.type == SExp::LIST && exp.empty())
+ AST* exp = readExpression(cursor, std::cin);
+ if (exp->to<ATuple*>() && exp->to<ATuple*>()->empty())
break;
AST* body = cenv.penv.parse(exp); // Parse input
diff --git a/src/tuplr.cpp b/src/tuplr.cpp
index e9bcae9..f8cc246 100644
--- a/src/tuplr.cpp
+++ b/src/tuplr.cpp
@@ -92,7 +92,7 @@ main(int argc, char** argv)
ifstream is(files.front().c_str());
if (is.good()) {
Cursor loc;
- SExp exp = readExpression(loc, is);
+ AST* exp = readExpression(loc, is);
AST* ast = penv.parse(exp);
pprint(cout, ast);
}
diff --git a/src/tuplr.hpp b/src/tuplr.hpp
index 087ce77..54d7098 100644
--- a/src/tuplr.hpp
+++ b/src/tuplr.hpp
@@ -62,37 +62,6 @@ struct Error {
string msg;
};
-/// Expression ::= Atom | (Expression*)
-template<typename Atom>
-struct Exp {
- typedef std::vector< Exp<Atom> > Vec;
-
- Exp(Cursor c) : type(LIST), loc(c), _vec(new Vec()) {}
- Exp(Cursor c, const Atom& a) : type(ATOM), loc(c), _atom(a) {}
-
- enum { ATOM, LIST } type;
-
- inline const Atom& atom() const { assert(type == ATOM); return _atom; }
-
- void push_back(const Exp<Atom>& exp) { assert(type == LIST); _vec->push_back(exp); }
-
- bool empty() const { assert(type == LIST); return _vec->empty(); }
- const Exp<Atom>& front() const { assert(type == LIST); return _vec->front(); }
-
- typedef typename Vec::const_iterator const_iterator;
- const_iterator begin() const { assert(type == LIST); return _vec->begin(); }
- const_iterator end() const { assert(type == LIST); return _vec->end(); }
-
- Cursor loc;
-
-private:
- Atom _atom;
- Vec* _vec;
-};
-
-template<typename Atom>
-extern ostream& operator<<(ostream& out, const Exp<Atom>& exp);
-
/// Lexical Address
struct LAddr {
LAddr(unsigned u=0, unsigned o=0) : up(u), over(o) {}
@@ -143,10 +112,9 @@ struct Env : public list< vector< pair<K,V> > > {
* Lexer: Text (istream) -> S-Expressions (SExp) *
***************************************************************************/
-class AString;
-typedef Exp<AString*> SExp; ///< Textual S-Expression
+class AST;
+AST* readExpression(Cursor& cur, std::istream& in);
-SExp readExpression(Cursor& cur, std::istream& in);
/***************************************************************************
@@ -290,9 +258,9 @@ private:
/// Tuple (heterogeneous sequence of fixed length), e.g. "(a b c)"
struct ATuple : public AST {
ATuple(Cursor c) : AST(c), _len(0), _vec(0) {}
- ATuple(Cursor c, const ATuple& t) : AST(c), _len(t._len) {
+ ATuple(const ATuple& exp) : AST(exp.loc), _len(exp._len) {
_vec = (AST**)malloc(sizeof(AST*) * _len);
- memcpy(_vec, t._vec, sizeof(AST*) * _len);
+ memcpy(_vec, exp._vec, sizeof(AST*) * _len);
}
ATuple(Cursor c, AST* ast, va_list args) : AST(c), _len(0), _vec(0) {
if (!ast) return;
@@ -306,6 +274,7 @@ struct ATuple : public AST {
newvec[_len++] = ast;
_vec = newvec;
}
+ const AST* front() const { assert(_len > 0); return _vec[0]; }
const AST* at(size_t i) const { assert(i < _len); return _vec[i]; }
AST*& at(size_t i) { assert(i < _len); return _vec[i]; }
size_t size() const { return _len; }
@@ -456,7 +425,7 @@ struct AFn : public ATuple {
/// Function call/application, e.g. "(func arg1 arg2)"
struct ACall : public ATuple {
- ACall(const SExp& e, const ATuple& t) : ATuple(e.loc, t) {}
+ ACall(const ATuple* exp) : ATuple(*exp) {}
ACall(Cursor c, AST* ast, va_list args) : ATuple(c, ast, args) {}
void constrain(TEnv& tenv, Constraints& c) const;
AST* cps(TEnv& tenv, AST* cont);
@@ -466,7 +435,7 @@ struct ACall : public ATuple {
/// Definition special form, e.g. "(def x 2)"
struct ADef : public ACall {
- ADef(const SExp& e, const ATuple& t) : ACall(e, t) {}
+ ADef(const ATuple* exp) : ACall(exp) {}
ADef(Cursor c, AST* ast, va_list args) : ACall(c, ast, args) {}
const ASymbol* sym() const {
const ASymbol* sym = at(1)->to<const ASymbol*>();
@@ -485,7 +454,7 @@ struct ADef : public ACall {
/// Conditional special form, e.g. "(if cond thenexp elseexp)"
struct AIf : public ACall {
- AIf(const SExp& e, const ATuple& t) : ACall(e, t) {}
+ AIf(const ATuple* exp) : ACall(exp) {}
AIf(Cursor c, AST* ast, va_list args) : ACall(c, ast, args) {}
void constrain(TEnv& tenv, Constraints& c) const;
AST* cps(TEnv& tenv, AST* cont);
@@ -494,7 +463,7 @@ struct AIf : public ACall {
/// Primitive (builtin arithmetic function), e.g. "(+ 2 3)"
struct APrimitive : public ACall {
- APrimitive(const SExp& e, const ATuple& t) : ACall(e, t) {}
+ APrimitive(const ATuple* exp) : ACall(exp) {}
bool value() const {
ATuple::const_iterator i = begin();
for (++i; i != end(); ++i)
@@ -515,8 +484,8 @@ struct APrimitive : public ACall {
/// Parse Time Environment (really just a symbol table)
struct PEnv : private map<const string, ASymbol*> {
PEnv() : symID(0) {}
- typedef AST* (*PF)(PEnv&, const SExp&, void*); ///< Parse Function
- typedef SExp (*MF)(PEnv&, const SExp&); ///< Macro Function
+ typedef AST* (*PF)(PEnv&, const AST*, void*); ///< Parse Function
+ typedef AST* (*MF)(PEnv&, const AST*); ///< Macro Function
struct Handler { Handler(PF f, void* a=0) : func(f), arg(a) {} PF func; void* arg; };
map<const string, Handler> aHandlers; ///< Atom parse functions
map<const string, Handler> lHandlers; ///< List parse functions
@@ -548,36 +517,43 @@ struct PEnv : private map<const string, ASymbol*> {
return sym;
}
}
- ATuple parseTuple(const SExp& e) {
- ATuple ret(e.loc);
- FOREACH(SExp::const_iterator, i, e)
- ret.push_back(parse(*i));
+ ATuple* parseTuple(const ATuple* e) {
+ ATuple* ret = new ATuple(e->loc);
+ FOREACH(ATuple::const_iterator, i, *e)
+ ret->push_back(parse(*i));
return ret;
}
- AST* parse(const SExp& exp) {
- if (exp.type == SExp::LIST) {
- if (exp.empty()) throw Error(exp.loc, "call to empty list");
- if (exp.front().type == SExp::ATOM) {
- MF mf = mac(*exp.front().atom());
- SExp expanded = (mf ? mf(*this, exp) : exp);
-
- const PEnv::Handler* h = handler(true, *expanded.front().atom());
+ AST* parse(const AST* exp) {
+ const ATuple* tup = exp->to<const ATuple*>();
+ if (tup) {
+ if (tup->empty()) throw Error(exp->loc, "call to empty list");
+ if (!tup->front()->to<const ATuple*>()) {
+ const AString* str = tup->front()->to<const AString*>();
+ assert(str);
+ MF mf = mac(*str);
+ const AST* expanded = (mf ? mf(*this, exp) : exp);
+ const ATuple* expanded_tup = expanded->to<const ATuple*>();
+ const PEnv::Handler* h = handler(true, *expanded_tup->front()->to<const AString*>());
if (h)
return h->func(*this, expanded, h->arg);
}
- return new ACall(exp, parseTuple(exp)); // Parse as regular call
- } else if (isdigit((*exp.atom())[0])) {
- const std::string& s = *exp.atom();
+ ATuple* parsed_tup = parseTuple(tup); // FIXME: leak
+ return new ACall(parsed_tup); // Parse as regular call
+ }
+ const AString* str = exp->to<const AString*>();
+ assert(str);
+ if (isdigit((*str)[0])) {
+ const std::string& s = *str;
if (s.find('.') == string::npos)
- return new ALiteral<int32_t>(strtol(s.c_str(), NULL, 10), exp.loc);
+ return new ALiteral<int32_t>(strtol(s.c_str(), NULL, 10), exp->loc);
else
- return new ALiteral<float>(strtod(s.c_str(), NULL), exp.loc);
+ return new ALiteral<float>(strtod(s.c_str(), NULL), exp->loc);
} else {
- const PEnv::Handler* h = handler(false, *exp.atom());
+ const PEnv::Handler* h = handler(false, *str);
if (h)
return h->func(*this, exp, h->arg);
}
- return sym(*exp.atom(), exp.loc);
+ return sym(*exp->to<const AString*>(), exp->loc);
}
unsigned symID;
};