From b754068a1e11cf480469836c6a04c6614f4d63c5 Mon Sep 17 00:00:00 2001 From: David Robillard Date: Sat, 7 Mar 2009 04:35:13 +0000 Subject: Stream based serialisation of AST nodes (can write arbitrarily large expressions without chewing memory). git-svn-id: http://svn.drobilla.net/resp/tuplr@75 ad02d1e2-f140-0410-9f75-f8b11f17cedd --- Makefile | 2 +- llvm.cpp | 4 ++-- tuplr.hpp | 32 ++++++++++---------------------- write.cpp | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 68 insertions(+), 25 deletions(-) create mode 100644 write.cpp diff --git a/Makefile b/Makefile index 001c37d..5ab2806 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,7 @@ LLVM_LDFLAGS=`llvm-config --ldflags --libs core jit native` CXXFLAGS=-O0 -g -Wall -Wextra -Wno-unused-parameter $(LLVM_CXXFLAGS) LDFLAGS=$(LLVM_LDFLAGS) -lm -tuplr: tuplr.o typing.o llvm.o +tuplr: tuplr.o typing.o llvm.o write.o g++ -o $@ $^ $(LDFLAGS) %.o: %.cpp tuplr.hpp diff --git a/llvm.cpp b/llvm.cpp index c0c46c9..3ccb1d7 100644 --- a/llvm.cpp +++ b/llvm.cpp @@ -540,7 +540,7 @@ eval(CEnv& cenv, const string& name, istream& is) cenv.optimise(f); cenv.log.out << call(resultType, cenv.engine.engine->getPointerToFunction(f)) - << " : " << resultType->str() << endl; + << " : " << resultType << endl; } catch (Error& e) { cenv.log.err << e.what() << endl; return 1; @@ -584,7 +584,7 @@ repl(CEnv& cenv) } else { cenv.log.out << "; " << cenv.compile(body); } - cenv.log.out << " : " << cenv.tenv.type(body)->str() << endl; + cenv.log.out << " : " << cenv.tenv.type(body) << endl; } catch (Error& e) { cenv.log.err << e.what() << endl; } diff --git a/tuplr.hpp b/tuplr.hpp index 29b8463..a931f8c 100644 --- a/tuplr.hpp +++ b/tuplr.hpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -95,19 +96,22 @@ struct CEngine; ///< Backend data (opaque) struct TEnv; ///< Type-Time Environment struct CEnv; ///< Compile-Time Environment +struct AST; +extern ostream& operator<<(ostream& out, const AST* ast); + /// Base class for all AST nodes struct AST { AST(Cursor c=Cursor()) : loc(c) {} virtual ~AST() {} - virtual string str() const = 0; virtual bool operator==(const AST& o) const = 0; virtual bool contains(const AST* child) const { return false; } virtual void constrain(TEnv& tenv) const {} virtual void lift(CEnv& cenv) {} + string str() const { ostringstream ss; ss << this; return ss.str(); } Cursor loc; private: friend class CEnv; - virtual CValue compile(CEnv& cenv) = 0; + virtual CValue compile(CEnv& cenv) = 0; }; /// Literal value @@ -118,7 +122,6 @@ struct ASTLiteral : public AST { const ASTLiteral* r = dynamic_cast*>(&rhs); return (r && (val == r->val)); } - string str() const { return (format("%1%") % val).str(); } void constrain(TEnv& tenv) const; CValue compile(CEnv& cenv); const VT val; @@ -127,12 +130,12 @@ struct ASTLiteral : public AST { /// Symbol, e.g. "a" struct ASTSymbol : public AST { bool operator==(const AST& rhs) const { return this == &rhs; } - string str() const { return cppstr; } void lift(CEnv& cenv); CValue compile(CEnv& cenv); private: friend class PEnv; ASTSymbol(const string& s, Cursor c) : AST(c), cppstr(s) {} + friend ostream& operator<<(ostream&, const AST*); const string cppstr; }; @@ -147,12 +150,6 @@ struct ASTTuple : public AST, public vector { push_back(a); va_end(args); } - string str() const { - string ret = "("; - for (size_t i = 0; i != size(); ++i) - ret += (at(i) ? at(i)->str() : "NULL") + ((i != size() - 1) ? " " : ""); - return ret + ")"; - } bool operator==(const AST& rhs) const { const ASTTuple* rt = dynamic_cast(&rhs); if (!rt || rt->size() != size()) return false; @@ -189,14 +186,6 @@ struct AType : public ASTTuple { push_back(a); va_end(args); } - string str() const { - switch (kind) { - case VAR: return (format("?%1%") % id).str(); - case PRIM: return at(0)->str(); - case EXPR: return ASTTuple::str(); - } - return ""; // never reached - } void constrain(TEnv& tenv) const {} CValue compile(CEnv& cenv) { return NULL; } bool var() const { return kind == VAR; } @@ -241,10 +230,9 @@ struct Funcs : public list< pair > { /// Closure (first-class function with captured lexical bindings) struct ASTClosure : public ASTTuple { - ASTClosure(Cursor c, ASTTuple* p, AST* b, const string& n="") - : ASTTuple(c, 0, p, b, NULL), name(n) {} + ASTClosure(Cursor c, ASTSymbol* fn, ASTTuple* p, AST* b, const string& n="") + : ASTTuple(c, fn, p, b, NULL), name(n) {} bool operator==(const AST& rhs) const { return this == &rhs; } - string str() const { return (format("%1%") % this).str(); } void constrain(TEnv& tenv) const; void lift(CEnv& cenv); CValue compile(CEnv& cenv); @@ -392,7 +380,7 @@ inline AST* parseFn(PEnv& penv, const SExp& exp, void* arg) { SExp::List::const_iterator a = exp.list.begin(); ++a; - return new ASTClosure(exp.loc, + return new ASTClosure(exp.loc, penv.sym("fn"), new ASTTuple(pmap(penv, *a++)), parseExpression(penv, *a++)); } diff --git a/write.cpp b/write.cpp new file mode 100644 index 0000000..b5784ab --- /dev/null +++ b/write.cpp @@ -0,0 +1,55 @@ +/* Tuplr Serialisation + * Copyright (C) 2008-2009 David Robillard + * + * Tuplr is free software: you can redistribute it and/or modify it under + * the terms of the GNU Affero General Public License as published by the + * Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * Tuplr is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General + * Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with Tuplr. If not, see . + */ + +#include "tuplr.hpp" + +ostream& +operator<<(ostream& out, const AST* ast) +{ +#define TRY_WRITE_LITERAL(T) \ + const ASTLiteral* lit ## T = dynamic_cast*>(ast); \ + if (lit ## T) \ + return out << (lit ## T)->val; + + TRY_WRITE_LITERAL(int32_t); + TRY_WRITE_LITERAL(float); + TRY_WRITE_LITERAL(bool); + + const ASTSymbol* sym = dynamic_cast(ast); + if (sym) + return out << sym->cppstr; + + const AType* type = dynamic_cast(ast); + if (type) { + switch (type->kind) { + case AType::VAR: return out << "?" << type->id; + case AType::PRIM: return out << type->at(0); + case AType::EXPR: break; // will catch Tuple case below + } + } + + const ASTTuple* tup = dynamic_cast(ast); + if (tup) { + out << "("; + for (size_t i = 0; i != tup->size(); ++i) + out << tup->at(i) << ((i != tup->size() - 1) ? " " : ""); + return out << ")"; + } + + return out << "?"; +} + -- cgit v1.2.1