<commit_before>#include <iostream>
#include <memory>
#include <llvm/ADT/STLExtras.h>
#include "parser.hpp"
#include "debug.hpp"

namespace llscm {
	using namespace std;
	using namespace llvm;

	bool Parser::match(const Token & tok, const Token && expected) {
		if (tok != expected) {
			stringstream ss;
			ss << "Expected token \"" << expected.name << "\".";
			error(ss.str());
			return false;
		}
		return true;
	}

	void Parser::error(const string & msg) {
		cerr << "Error: " << msg << endl;
		err_flag = true;
	}

	/*
	 * prog = form { form }
	 */
	vector<P_ScmObj> Parser::NT_Prog() {
		const Token * tok;
		vector<P_ScmObj> prog;
		bool first = true;

		D(cout << "NT_Prog: " << endl);

		while (true) {
			tok = reader->nextToken();

			if (!tok) {
				if (first) {
					error("Program is empty.");
					return prog;
				}
				else break;
			}
			//D(cout << tok->name << endl);
			P_ScmObj form = NT_Form();
			if (fail()) break;
			prog.push_back(move(form));
			first = false;
		}

		return prog;
	}

	/*
	 * form = "(" def ")" | expr
	 * def = "define" sym expr ...
	 * expr = atom | ( "(" list ")" )
	 */
	P_ScmObj Parser::NT_Form() {
		const Token * tok = reader->currToken();
		P_ScmObj obj;

		D(cout << "NT_Form: " << endl);
		D(cout << tok->name << endl);

		if (tok->t == KWRD && tok->kw == KW_LPAR) {
			tok = reader->nextToken();
			if (!tok) {
				error("Reached EOF while parsing a list.");
				return nullptr;
			}
			//D(cout << tok->name << endl);
			if (tok->t == KWRD && (tok->kw == KW_DEFINE || tok->kw == KW_LET)) {
				// Current token is "define" or "let"
				obj = NT_Def();
				if (fail()) return nullptr;
			}
			else {
				// Current token is the first token of list
				obj = NT_List();
				if (fail()) return nullptr;
			}
			if (!match(*reader->currToken(), Token(KW_RPAR))) {
				return nullptr;
			}
			return obj;
		}
		// Anything other than "(" must be an atom
		return NT_Atom();
	}

	/*
	 * def = "define" sym expr
	 *		 | "define" "(" sym symlist ")" body
	 *		 | "let" "(" bindlist ")" body
	 */
	P_ScmObj Parser::NT_Def() {
		const Token * tok = reader->currToken();
		P_ScmObj name, lst, expr;

		if (tok->kw == KW_DEFINE) {
			D(cout << "NT_Def: " << endl);

			tok = reader->nextToken();
			if (!tok) {
				error("Reached EOF while parsing a definition.");
				return nullptr;
			}
			D(cout << tok->name << endl);

			if (tok->t == KWRD && tok->kw == KW_LPAR) {
				// Function definition
				tok = reader->nextToken();
				if (!tok || tok->t != SYM) {
					error("Missing function name in definition.");
					return nullptr;
				}
				name = make_unique<ScmSym>(tok->name);
				reader->nextToken();
				lst = NT_SymList();
				if (fail()) return nullptr;

				if (!match(*reader->currToken(), Token(KW_RPAR))) {
					return nullptr;
				}
				reader->nextToken();

				return make_unique<ScmDefineFuncSyntax>(move(name), move(lst), NT_Body());
			}
			if (tok->t != SYM) {
				error("Expected symbol as first argument of define.");
				return nullptr;
			}
			name = make_unique<ScmSym>(tok->name);
			tok = reader->nextToken();
			//D(cout << tok->name << endl);
			if (tok && tok->t == KWRD && tok->kw == KW_RPAR) {
				error("Missing expression in variable definition.");
				return nullptr;
			}

			expr = NT_Expr();
			if (fail()) return nullptr;
			tok = reader->nextToken();
			//D(cout << tok->name << endl);

			return make_unique<ScmDefineVarSyntax>(move(name), move(expr));
		}
		else { // tok->kw == KW_LET
			D(cout << "NT_Let: " << endl);

			if (!match(*reader->nextToken(), Token(KW_LPAR))) {
				return nullptr;
			}
			tok = reader->nextToken();
			//D(cout << tok->name << endl);

			lst = NT_BindList();
			if (fail()) return nullptr;
			if (!match(*reader->currToken(), Token(KW_RPAR))) {
				return nullptr;
			}
			tok = reader->nextToken();
			//D(cout << tok->name << endl);

			return make_unique<ScmLetSyntax>(move(lst), NT_Body());
		}
		//return nullptr;
	}

	/*
	 * expr = atom | ( "(" list ")" )
	 */
	P_ScmObj Parser::NT_Expr() {
		const Token * tok = reader->currToken();
		P_ScmObj obj;

		D(cout << "NT_Expr: " << endl);

		if (!tok) {
			error("Expected expression.");
			return nullptr;
		}

		if (tok->t == KWRD && tok->kw == KW_LPAR) {
			tok = reader->nextToken();
			obj = NT_List();
			if (fail()) return nullptr;

			if (!match(*reader->currToken(), Token(KW_RPAR))) {
				return nullptr;
			}
			return obj;
		}
		D(cout << tok->name << endl);
		return NT_Atom();
	}

	/*
	 * atom = str | sym | int | float | true | false | null
	 */
	P_ScmObj Parser::NT_Atom() {
		const Token * tok = reader->currToken();

		switch (tok->t) {
		case STR:
			return make_unique<ScmStr>(tok->name);
		case SYM:
			return make_unique<ScmSym>(tok->name);
		case INT:
			return make_unique<ScmInt>(tok->int_val);
		case FLOAT:
			return make_unique<ScmFloat>(tok->float_val);
		default:;
		}

		if (tok->t != KWRD) {
			error("Invalid token for an atom.");
			return nullptr;
		}
		switch (tok->kw) {
		case KW_TRUE:
			return make_unique<ScmTrue>();
		case KW_FALSE:
			return make_unique<ScmFalse>();
		case KW_NULL:
			return make_unique<ScmNull>();
		default:
			error("Invalid token for an atom.");
		}
		return nullptr;
	}

	/*
	 * list = { expr }
	 */
	P_ScmObj Parser::NT_List() {
		const Token * tok = reader->currToken();
		P_ScmObj obj;

		D(cout << "NT_List: " << endl);
		if (!tok) {
			error("Reached EOF while parsing a list.");
			return nullptr;
		}

		D(cout << tok->name << endl);

		if (tok->t == KWRD && tok->kw == KW_RPAR) {
			// Empty list
			return make_unique<ScmNull>();
		}
		obj = NT_Expr();
		reader->nextToken();
		return make_unique<ScmCons>(move(obj), NT_List());
	}

	/*
	 * symlist = { sym }
	 */
	P_ScmObj Parser::NT_SymList() {
		const Token * tok = reader->currToken();
		P_ScmObj obj;

		if (!tok) {
			error("Reached EOF while parsing a list.");
			return nullptr;
		}

		if (tok->t == KWRD && tok->kw == KW_RPAR) {
			// Empty list
			return make_unique<ScmNull>();
		}
		if (tok->t != SYM) {
			error("Invalid expression in argument list. Only symbols are allowed.");
			return nullptr;
		}
		obj = make_unique<ScmSym>(tok->name);
		reader->nextToken();
		return make_unique<ScmCons>(move(obj), NT_SymList());
	}

	/*
	 * bindlist = { "(" sym expr ")" }
	 */
	P_ScmObj Parser::NT_BindList() {
		const Token * tok = reader->currToken();
		vector<P_ScmObj> vec;

		D(cout << "NT_BindList" << endl);
		if (!tok) {
			error("Reached EOF while parsing a list.");
			return nullptr;
		}

		D(cout << tok->name << endl);

		if (tok->t == KWRD && tok->kw == KW_RPAR) {
			// Empty list
			return make_unique<ScmNull>();
		}
		if (!match(*reader->currToken(), Token(KW_LPAR))) {
			return nullptr;
		}
		tok = reader->nextToken();
		//D(cout << tok->name << endl);

		if (!tok || tok->t != SYM) {
			error("First element of binding list must be a symbol.");
			return nullptr;
		}

		vec.push_back(make_unique<ScmSym>(tok->name));
		tok = reader->nextToken();

		if (!tok) {
			error("Reached EOF while parsing a list.");
			return nullptr;
		}

		if (tok->t == KWRD && tok->kw == KW_RPAR) {
			error("Binding list must have exactly two elements: id, expression.");
			return nullptr;
		}
		//D(cout << tok->name << endl);

		vec.push_back(NT_Expr());
		if (!match(*reader->nextToken(), Token(KW_RPAR))) {
			return nullptr;
		}
		tok = reader->nextToken();
		//D(cout << tok->name << endl);

		return make_unique<ScmCons>(makeScmList(move(vec)), NT_BindList());
	}

	/*
	 * body = { "(" def ")" } expr { expr }
	 */
	P_ScmObj Parser::NT_Body() {
		vector<P_ScmObj> lst;
		const Token * tok = reader->currToken();
		P_ScmObj obj;
		bool parsing_defs = true;
		bool no_expr = true;

		D(cout << "NT_Body" << endl);

		while (parsing_defs) {
			if (!tok) {
				error("Reached EOF while parsing a body.");
				return nullptr;
			}
			D(cout << tok->name << endl);

			if (tok->t == KWRD && tok->kw == KW_RPAR) {
				if (no_expr) {
					error("Missing expression in a body.");
					return nullptr;
				}
				break;
			}
			obj = NT_Form();
			if (dynamic_cast<ScmDefineSyntax*>(obj.get()) == nullptr) {
				parsing_defs = false;
			}
			if (dynamic_cast<ScmLetSyntax*>(obj.get()) != nullptr) {
				no_expr = false;
			}
			lst.push_back(move(obj));
			tok = reader->nextToken();
		}

		do {
			if (!tok) {
				error("Reached EOF while parsing a body.");
				return nullptr;
			}
			if (tok->t == KWRD && tok->kw == KW_RPAR) {
				return makeScmList(move(lst));
			}
			lst.push_back(NT_Expr());
			tok = reader->nextToken();
		} while (true);
	}
}
<commit_msg>Fixed a bug in NT_List.<commit_after>#include <iostream>
#include <memory>
#include <llvm/ADT/STLExtras.h>
#include "parser.hpp"
#include "debug.hpp"

namespace llscm {
	using namespace std;
	using namespace llvm;

	bool Parser::match(const Token & tok, const Token && expected) {
		if (tok != expected) {
			stringstream ss;
			ss << "Expected token \"" << expected.name << "\".";
			error(ss.str());
			return false;
		}
		return true;
	}

	void Parser::error(const string & msg) {
		cerr << "Error: " << msg << endl;
		err_flag = true;
	}

	/*
	 * prog = form { form }
	 */
	vector<P_ScmObj> Parser::NT_Prog() {
		const Token * tok;
		vector<P_ScmObj> prog;
		bool first = true;

		D(cout << "NT_Prog: " << endl);

		while (true) {
			tok = reader->nextToken();

			if (!tok) {
				if (first) {
					error("Program is empty.");
					return prog;
				}
				else break;
			}
			//D(cout << tok->name << endl);
			P_ScmObj form = NT_Form();
			if (fail()) break;
			prog.push_back(move(form));
			first = false;
		}

		return prog;
	}

	/*
	 * form = "(" def ")" | expr
	 * def = "define" sym expr ...
	 * expr = atom | ( "(" list ")" )
	 */
	P_ScmObj Parser::NT_Form() {
		const Token * tok = reader->currToken();
		P_ScmObj obj;

		D(cout << "NT_Form: " << endl);
		D(cout << tok->name << endl);

		if (tok->t == KWRD && tok->kw == KW_LPAR) {
			tok = reader->nextToken();
			if (!tok) {
				error("Reached EOF while parsing a list.");
				return nullptr;
			}
			//D(cout << tok->name << endl);
			if (tok->t == KWRD && (tok->kw == KW_DEFINE || tok->kw == KW_LET)) {
				// Current token is "define" or "let"
				obj = NT_Def();
				if (fail()) return nullptr;
			}
			else {
				// Current token is the first token of list
				obj = NT_List();
				if (fail()) return nullptr;
			}
			if (!match(*reader->currToken(), Token(KW_RPAR))) {
				return nullptr;
			}
			return obj;
		}
		// Anything other than "(" must be an atom
		return NT_Atom();
	}

	/*
	 * def = "define" sym expr
	 *		 | "define" "(" sym symlist ")" body
	 *		 | "let" "(" bindlist ")" body
	 */
	P_ScmObj Parser::NT_Def() {
		const Token * tok = reader->currToken();
		P_ScmObj name, lst, expr;

		if (tok->kw == KW_DEFINE) {
			D(cout << "NT_Def: " << endl);

			tok = reader->nextToken();
			if (!tok) {
				error("Reached EOF while parsing a definition.");
				return nullptr;
			}
			D(cout << tok->name << endl);

			if (tok->t == KWRD && tok->kw == KW_LPAR) {
				// Function definition
				tok = reader->nextToken();
				if (!tok || tok->t != SYM) {
					error("Missing function name in definition.");
					return nullptr;
				}
				name = make_unique<ScmSym>(tok->name);
				reader->nextToken();
				lst = NT_SymList();
				if (fail()) return nullptr;

				if (!match(*reader->currToken(), Token(KW_RPAR))) {
					return nullptr;
				}
				reader->nextToken();

				return make_unique<ScmDefineFuncSyntax>(move(name), move(lst), NT_Body());
			}
			if (tok->t != SYM) {
				error("Expected symbol as first argument of define.");
				return nullptr;
			}
			name = make_unique<ScmSym>(tok->name);
			tok = reader->nextToken();
			//D(cout << tok->name << endl);
			if (tok && tok->t == KWRD && tok->kw == KW_RPAR) {
				error("Missing expression in variable definition.");
				return nullptr;
			}

			expr = NT_Expr();
			if (fail()) return nullptr;
			tok = reader->nextToken();
			//D(cout << tok->name << endl);

			return make_unique<ScmDefineVarSyntax>(move(name), move(expr));
		}
		else { // tok->kw == KW_LET
			D(cout << "NT_Let: " << endl);

			if (!match(*reader->nextToken(), Token(KW_LPAR))) {
				return nullptr;
			}
			tok = reader->nextToken();
			//D(cout << tok->name << endl);

			lst = NT_BindList();
			if (fail()) return nullptr;
			if (!match(*reader->currToken(), Token(KW_RPAR))) {
				return nullptr;
			}
			tok = reader->nextToken();
			//D(cout << tok->name << endl);

			return make_unique<ScmLetSyntax>(move(lst), NT_Body());
		}
		//return nullptr;
	}

	/*
	 * expr = atom | ( "(" list ")" )
	 */
	P_ScmObj Parser::NT_Expr() {
		const Token * tok = reader->currToken();
		P_ScmObj obj;

		D(cout << "NT_Expr: " << endl);

		if (!tok) {
			error("Expected expression.");
			return nullptr;
		}

		if (tok->t == KWRD && tok->kw == KW_LPAR) {
			tok = reader->nextToken();
			obj = NT_List();
			if (fail()) return nullptr;

			if (!match(*reader->currToken(), Token(KW_RPAR))) {
				return nullptr;
			}
			return obj;
		}
		D(cout << tok->name << endl);
		return NT_Atom();
	}

	/*
	 * atom = str | sym | int | float | true | false | null
	 */
	P_ScmObj Parser::NT_Atom() {
		const Token * tok = reader->currToken();

		switch (tok->t) {
		case STR:
			return make_unique<ScmStr>(tok->name);
		case SYM:
			return make_unique<ScmSym>(tok->name);
		case INT:
			return make_unique<ScmInt>(tok->int_val);
		case FLOAT:
			return make_unique<ScmFloat>(tok->float_val);
		default:;
		}

		if (tok->t != KWRD) {
			error("Invalid token for an atom.");
			return nullptr;
		}
		switch (tok->kw) {
		case KW_TRUE:
			return make_unique<ScmTrue>();
		case KW_FALSE:
			return make_unique<ScmFalse>();
		case KW_NULL:
			return make_unique<ScmNull>();
		default:
			error("Invalid token for an atom.");
		}
		return nullptr;
	}

	/*
	 * list = { expr }
	 */
	P_ScmObj Parser::NT_List() {
		const Token * tok = reader->currToken();
		P_ScmObj obj;

		D(cout << "NT_List: " << endl);
		if (!tok) {
			error("Reached EOF while parsing a list.");
			return nullptr;
		}

		D(cout << tok->name << endl);

		if (tok->t == KWRD && tok->kw == KW_RPAR) {
			// Empty list
			return make_unique<ScmNull>();
		}
		obj = NT_Expr();
		if (fail()) return nullptr;
		reader->nextToken();
		return make_unique<ScmCons>(move(obj), NT_List());
	}

	/*
	 * symlist = { sym }
	 */
	P_ScmObj Parser::NT_SymList() {
		const Token * tok = reader->currToken();
		P_ScmObj obj;

		if (!tok) {
			error("Reached EOF while parsing a list.");
			return nullptr;
		}

		if (tok->t == KWRD && tok->kw == KW_RPAR) {
			// Empty list
			return make_unique<ScmNull>();
		}
		if (tok->t != SYM) {
			error("Invalid expression in argument list. Only symbols are allowed.");
			return nullptr;
		}
		obj = make_unique<ScmSym>(tok->name);
		reader->nextToken();
		return make_unique<ScmCons>(move(obj), NT_SymList());
	}

	/*
	 * bindlist = { "(" sym expr ")" }
	 */
	P_ScmObj Parser::NT_BindList() {
		const Token * tok = reader->currToken();
		vector<P_ScmObj> vec;

		D(cout << "NT_BindList" << endl);
		if (!tok) {
			error("Reached EOF while parsing a list.");
			return nullptr;
		}

		D(cout << tok->name << endl);

		if (tok->t == KWRD && tok->kw == KW_RPAR) {
			// Empty list
			return make_unique<ScmNull>();
		}
		if (!match(*reader->currToken(), Token(KW_LPAR))) {
			return nullptr;
		}
		tok = reader->nextToken();
		//D(cout << tok->name << endl);

		if (!tok || tok->t != SYM) {
			error("First element of binding list must be a symbol.");
			return nullptr;
		}

		vec.push_back(make_unique<ScmSym>(tok->name));
		tok = reader->nextToken();

		if (!tok) {
			error("Reached EOF while parsing a list.");
			return nullptr;
		}

		if (tok->t == KWRD && tok->kw == KW_RPAR) {
			error("Binding list must have exactly two elements: id, expression.");
			return nullptr;
		}
		//D(cout << tok->name << endl);

		vec.push_back(NT_Expr());
		if (!match(*reader->nextToken(), Token(KW_RPAR))) {
			return nullptr;
		}
		tok = reader->nextToken();
		//D(cout << tok->name << endl);

		return make_unique<ScmCons>(makeScmList(move(vec)), NT_BindList());
	}

	/*
	 * body = { "(" def ")" } expr { expr }
	 */
	P_ScmObj Parser::NT_Body() {
		vector<P_ScmObj> lst;
		const Token * tok = reader->currToken();
		P_ScmObj obj;
		bool parsing_defs = true;
		bool no_expr = true;

		D(cout << "NT_Body" << endl);

		while (parsing_defs) {
			if (!tok) {
				error("Reached EOF while parsing a body.");
				return nullptr;
			}
			D(cout << tok->name << endl);

			if (tok->t == KWRD && tok->kw == KW_RPAR) {
				if (no_expr) {
					error("Missing expression in a body.");
					return nullptr;
				}
				break;
			}
			obj = NT_Form();
			if (dynamic_cast<ScmDefineSyntax*>(obj.get()) == nullptr) {
				parsing_defs = false;
			}
			if (dynamic_cast<ScmLetSyntax*>(obj.get()) != nullptr) {
				no_expr = false;
			}
			lst.push_back(move(obj));
			tok = reader->nextToken();
		}

		do {
			if (!tok) {
				error("Reached EOF while parsing a body.");
				return nullptr;
			}
			if (tok->t == KWRD && tok->kw == KW_RPAR) {
				return makeScmList(move(lst));
			}
			lst.push_back(NT_Expr());
			tok = reader->nextToken();
		} while (true);
	}
}
<|endoftext|>


<commit_before>#ifndef __Z2H_PARSER__
#define __Z2H_PARSER__ = 1

#include <cmath>
#include <string>
#include <vector>
#include <fstream>
#include <sstream>
#include <iostream>
#include <stddef.h>
#include <sys/stat.h>
#include <functional>

#include "symbol.hpp"
#include "token.hpp"
#include "binder.hpp"

using namespace std::placeholders;

namespace z2h {

    template <typename TParser>
    struct Parser : public Binder<TParser> {

        std::string                 source;
        size_t                      position;
        std::vector<Token *>        tokens;
        size_t                      index;

        ~Parser() {
            while (!tokens.empty())
                delete tokens.back(), tokens.pop_back();
        }

        Parser()
            : source("")
            , position(0)
            , tokens({})
            , index(0) {
        }

        // Exception must be defined by the inheriting parser, throw exceptions defined there
        virtual std::exception Exception(const char *file, size_t line, const std::string &message = "") = 0;

        // Symbols must be defined by the inheriting parser
        virtual std::vector<Symbol *> Symbols() = 0;

        // the default for the eof symbol is first in in the list of symbols
        virtual Symbol * EofSymbol() {
            return Symbols()[0];
        }

        // the default for the eos symbol is second in in the list of symbols
        virtual Symbol * EosSymbol() {
            return Symbols()[1];
        }

        std::string Open(const std::string &filename) {
            struct stat buffer;
            if (stat(filename.c_str(), &buffer) != 0)
                Exception(__FILE__, __LINE__, filename + " doesn't exist or is unreadable");
            std::ifstream file(filename);
            std::string text((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
            return text;
        }

        std::vector<Token *> TokenizeFile(const std::string &filename) {
            auto source = Open(filename);
            return Tokenize(source);
        }

        std::vector<Token *> Tokenize(std::string source) {
            this->index = 0;
            this->source = source;
            auto eof = EofSymbol();
            auto token = Consume();
            while (eof != token->symbol) {
                token = Consume();
            }
            return tokens;
        }

        virtual std::vector<Ast *> ParseFile(const std::string &filename) {
            auto source = Open(filename);
            return Parse(source);
        }

        virtual std::vector<Ast *> Parse(std::string source) {
            this->index = 0;
            this->source = source;
            return Statements();
        }

        virtual Token * Scan() {

            auto eof = EofSymbol();
            Token *match = nullptr;
            if (position < source.length()) {
                for (auto symbol : Symbols()) {
                    auto token = symbol->Scan(symbol, source.substr(position, source.length() - position), position);
                    if (nullptr == match) {
                        match = token;
                    }
                    else if (nullptr != token && (token->length > match->length || (token->symbol->lbp > match->symbol->lbp && token->length == match->length))) {
                        delete match;
                        match = token;
                    } else {
                        delete token;
                    }
                }
                if (nullptr == match) {
                    throw Exception(__FILE__, __LINE__, "Parser::Scan: invalid symbol");
                }
                return match;
            }
            return new Token(eof, "EOF", position, 0, false); //eof
        }

        virtual Token * LookAhead(size_t &distance, bool skips = false) {
            Token *token = nullptr;
            auto i = index;
            while (distance) {
                if (i < tokens.size()) {
                    token = tokens[i];
                }
                else {
                    token = Scan();
                    position += token->length;
                    tokens.push_back(token);
                }
                if (skips || !token->skip) {
                    --distance;
                }
                ++i;
            }
            distance = i - index;
            return token;
        }

        Token * LookAhead1() {
            size_t distance = 1;
            return this->LookAhead(distance);
        }

        Token * LookAhead2() {
            size_t distance = 2;
            return this->LookAhead(distance);
        }

        virtual Token * Consume(Symbol *expected = nullptr) {
            if (expected) {
                return Consume({expected});
            }
            return Consume({});
        }

        virtual Token * Consume(std::initializer_list<Symbol *> expectations) {
            size_t distance = 1;
            auto token = LookAhead(distance);
            if (expectations.size()) {
                for (auto expectation : expectations) {
                    if (expectation && expectation == token->symbol) {
                        index += distance;
                        return token;
                    }
                }
                return nullptr;
            }
            index += distance;
            return token;
        }

        virtual Ast * Expression(size_t rbp = 0) {

            auto *curr = Consume();
            size_t distance = 1;
            Ast *left = curr->symbol->Nud(curr);
            auto *next = LookAhead(distance);
            while (rbp < next->symbol->lbp) {
                curr = Consume();
                if (nullptr == curr->symbol->Led) {
                    std::cout << __LINE__ << "no Led: curr=" << *curr << std::endl;
                    std::ostringstream out;
                    out << "unexpected: nullptr==Led curr=" << *curr;
                    throw Exception(__FILE__, __LINE__, out.str());
                }
                left = curr->symbol->Led(left, curr);
                size_t distance = 1;
                next = LookAhead(distance);
            }
            return left;
        }

        virtual Ast * Statement() {
            size_t distance = 1;
            auto *la1 = LookAhead(distance);
            if (nullptr != la1->symbol->Std) {
                Consume();
                return la1->symbol->Std();
            }
            auto ast = Expression();
            return ast;
        }

        virtual std::vector<Ast *> Statements() {
            std::vector<Ast *> statements;
            auto eos = EosSymbol();
            auto statement = Statement();
            while (statement) {
                statements.push_back(statement);
                statement = Consume(eos) ? Statement() : nullptr;
            }
            return statements;
        }

        size_t Line() {
            return 0;
        }

        size_t Column() {
            return 0;
        }

    };

}

#endif /*__Z2H_PARSER__*/
<commit_msg>moved functions from z2h -> sota... -sai<commit_after>#ifndef __Z2H_PARSER__
#define __Z2H_PARSER__ = 1

#include <cmath>
#include <string>
#include <vector>
#include <fstream>
#include <sstream>
#include <iostream>
#include <stddef.h>
#include <sys/stat.h>
#include <functional>

#include "symbol.hpp"
#include "token.hpp"
#include "binder.hpp"

using namespace std::placeholders;

namespace z2h {

    template <typename TParser>
    struct Parser : public Binder<TParser> {

        std::string                 source;
        size_t                      position;
        std::vector<Token *>        tokens;
        size_t                      index;

        ~Parser() {
            while (!tokens.empty())
                delete tokens.back(), tokens.pop_back();
        }

        Parser()
            : source("")
            , position(0)
            , tokens({})
            , index(0) {
        }

        // Exception must be defined by the inheriting parser, throw exceptions defined there
        virtual std::exception Exception(const char *file, size_t line, const std::string &message = "") = 0;

        // Symbols must be defined by the inheriting parser
        virtual std::vector<Symbol *> Symbols() = 0;

        // the default for the eof symbol is first in in the list of symbols
        virtual Symbol * EofSymbol() {
            return Symbols()[0];
        }

        // the default for the eos symbol is second in in the list of symbols
        virtual Symbol * EosSymbol() {
            return Symbols()[1];
        }

        std::string Open(const std::string &filename) {
            struct stat buffer;
            if (stat(filename.c_str(), &buffer) != 0)
                Exception(__FILE__, __LINE__, filename + " doesn't exist or is unreadable");
            std::ifstream file(filename);
            std::string text((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
            return text;
        }

        virtual Token * Scan() {

            auto eof = EofSymbol();
            Token *match = nullptr;
            if (position < source.length()) {
                for (auto symbol : Symbols()) {
                    auto token = symbol->Scan(symbol, source.substr(position, source.length() - position), position);
                    if (nullptr == match) {
                        match = token;
                    }
                    else if (nullptr != token && (token->length > match->length || (token->symbol->lbp > match->symbol->lbp && token->length == match->length))) {
                        delete match;
                        match = token;
                    } else {
                        delete token;
                    }
                }
                if (nullptr == match) {
                    throw Exception(__FILE__, __LINE__, "Parser::Scan: invalid symbol");
                }
                return match;
            }
            return new Token(eof, "EOF", position, 0, false); //eof
        }

        virtual Token * LookAhead(size_t &distance, bool skips = false) {
            Token *token = nullptr;
            auto i = index;
            while (distance) {
                if (i < tokens.size()) {
                    token = tokens[i];
                }
                else {
                    token = Scan();
                    position += token->length;
                    tokens.push_back(token);
                }
                if (skips || !token->skip) {
                    --distance;
                }
                ++i;
            }
            distance = i - index;
            return token;
        }

        Token * LookAhead1() {
            size_t distance = 1;
            return this->LookAhead(distance);
        }

        Token * LookAhead2() {
            size_t distance = 2;
            return this->LookAhead(distance);
        }

        virtual Token * Consume(Symbol *expected = nullptr) {
            if (expected) {
                return Consume({expected});
            }
            return Consume({});
        }

        virtual Token * Consume(std::initializer_list<Symbol *> expectations) {
            size_t distance = 1;
            auto token = LookAhead(distance);
            if (expectations.size()) {
                for (auto expectation : expectations) {
                    if (expectation && expectation == token->symbol) {
                        index += distance;
                        return token;
                    }
                }
                return nullptr;
            }
            index += distance;
            return token;
        }

        virtual Ast * Expression(size_t rbp = 0) {

            auto *curr = Consume();
            size_t distance = 1;
            Ast *left = curr->symbol->Nud(curr);
            auto *next = LookAhead(distance);
            while (rbp < next->symbol->lbp) {
                curr = Consume();
                if (nullptr == curr->symbol->Led) {
                    std::cout << __LINE__ << "no Led: curr=" << *curr << std::endl;
                    std::ostringstream out;
                    out << "unexpected: nullptr==Led curr=" << *curr;
                    throw Exception(__FILE__, __LINE__, out.str());
                }
                left = curr->symbol->Led(left, curr);
                size_t distance = 1;
                next = LookAhead(distance);
            }
            return left;
        }

        virtual Ast * Statement() {
            size_t distance = 1;
            auto *la1 = LookAhead(distance);
            if (nullptr != la1->symbol->Std) {
                Consume();
                return la1->symbol->Std();
            }
            auto ast = Expression();
            return ast;
        }

        virtual std::vector<Ast *> Statements() {
            std::vector<Ast *> statements;
            auto eos = EosSymbol();
            auto statement = Statement();
            while (statement) {
                statements.push_back(statement);
                statement = Consume(eos) ? Statement() : nullptr;
            }
            return statements;
        }

        size_t Line() {
            return 0;
        }

        size_t Column() {
            return 0;
        }

    };

}

#endif /*__Z2H_PARSER__*/
<|endoftext|>


<commit_before>#include "asvgf/asvgf.h"

namespace idaten
{
    void AdvancedSVGFPathTracing::update(
        GLuint gltex,
        int width, int height,
        const aten::CameraParameter& camera,
        const std::vector<aten::GeomParameter>& shapes,
        const std::vector<aten::MaterialParameter>& mtrls,
        const std::vector<aten::LightParameter>& lights,
        const std::vector<std::vector<aten::GPUBvhNode>>& nodes,
        const std::vector<aten::PrimitiveParamter>& prims,
        uint32_t advancePrimNum,
        const std::vector<aten::vertex>& vtxs,
        uint32_t advanceVtxNum,
        const std::vector<aten::mat4>& mtxs,
        const std::vector<TextureResource>& texs,
        const EnvmapResource& envmapRsc)
    {
        idaten::SVGFPathTracing::update(
            gltex,
            width, height,
            camera,
            shapes,
            mtrls,
            lights,
            nodes,
            prims, advancePrimNum,
            vtxs, advanceVtxNum,
            mtxs,
            texs, envmapRsc);

        int tiledW = getTiledResolution(width);
        int tiledH = getTiledResolution(height);

        m_gradient[0].init(tiledW * tiledH);
        m_gradient[1].init(tiledW * tiledH);

        m_gradientSample.init(tiledW * tiledH);
    }

    void AdvancedSVGFPathTracing::onDenoise(
        const TileDomain& tileDomain,
        int width, int height,
        cudaSurfaceObject_t outputSurf)
    {
        m_tileDomain = tileDomain;

        if (m_mode == Mode::SVGF
            || m_mode == Mode::TF
            || m_mode == Mode::VAR)
        {
            // Sample Gradient.
            onSampleGradient(width, height);

            if (isFirstFrame()) {
                // Nothing is done...
                return;
            }
            else {
                // Create Gradient.
                onCreateGradient(width, height);

                displayTiledData(width, height, m_gradient[0], outputSurf);

                // TODO
                // Atrous Gradient.

                // TODO
                // Temporal Reprojection.
            }
        }

        if (m_mode == Mode::SVGF
            || m_mode == Mode::VAR)
        {
            onVarianceEstimation(outputSurf, width, height);
        }
    }
}<commit_msg>Fix line feed.<commit_after>#include "asvgf/asvgf.h"

namespace idaten
{
    void AdvancedSVGFPathTracing::update(
        GLuint gltex,
        int width, int height,
        const aten::CameraParameter& camera,
        const std::vector<aten::GeomParameter>& shapes,
        const std::vector<aten::MaterialParameter>& mtrls,
        const std::vector<aten::LightParameter>& lights,
        const std::vector<std::vector<aten::GPUBvhNode>>& nodes,
        const std::vector<aten::PrimitiveParamter>& prims,
        uint32_t advancePrimNum,
        const std::vector<aten::vertex>& vtxs,
        uint32_t advanceVtxNum,
        const std::vector<aten::mat4>& mtxs,
        const std::vector<TextureResource>& texs,
        const EnvmapResource& envmapRsc)
    {
        idaten::SVGFPathTracing::update(
            gltex,
            width, height,
            camera,
            shapes,
            mtrls,
            lights,
            nodes,
            prims, advancePrimNum,
            vtxs, advanceVtxNum,
            mtxs,
            texs, envmapRsc);

        int tiledW = getTiledResolution(width);
        int tiledH = getTiledResolution(height);

        m_gradient[0].init(tiledW * tiledH);
        m_gradient[1].init(tiledW * tiledH);

        m_gradientSample.init(tiledW * tiledH);
    }

    void AdvancedSVGFPathTracing::onDenoise(
        const TileDomain& tileDomain,
        int width, int height,
        cudaSurfaceObject_t outputSurf)
    {
        m_tileDomain = tileDomain;

        if (m_mode == Mode::SVGF
            || m_mode == Mode::TF
            || m_mode == Mode::VAR)
        {
            // Sample Gradient.
            onSampleGradient(width, height);

            if (isFirstFrame()) {
                // Nothing is done...
                return;
            }
            else {
                // Create Gradient.
                onCreateGradient(width, height);

                displayTiledData(width, height, m_gradient[0], outputSurf);

                // TODO
                // Atrous Gradient.

                // TODO
                // Temporal Reprojection.
            }
        }

        if (m_mode == Mode::SVGF
            || m_mode == Mode::VAR)
        {
            onVarianceEstimation(outputSurf, width, height);
        }
    }
}<|endoftext|>


<commit_before>/**
 *  @file Nasa9PolyMultiTempRegion.cpp
 *  Definitions for a single-species standard state object derived
 *  from \link Cantera::SpeciesThermoInterpType
 *    SpeciesThermoInterpType\endlink  based
 *  on the NASA 9 coefficient temperature polynomial form
 *  applied to one temperature region
 *  (see \ref spthermo and class
 *   \link Cantera::Nasa9Poly1 Nasa9Poly1\endlink).
 *
 *  This parameterization has one NASA temperature region.
 */
// Copyright 2007  Sandia National Laboratories

#include "cantera/base/ctexceptions.h"
#include "cantera/thermo/Nasa9PolyMultiTempRegion.h"

using namespace std;

namespace Cantera
{
Nasa9PolyMultiTempRegion::Nasa9PolyMultiTempRegion() :
    m_numTempRegions(0),
    m_currRegion(0)
{
}

Nasa9PolyMultiTempRegion::Nasa9PolyMultiTempRegion(vector<Nasa9Poly1*>& regionPts) :
    m_numTempRegions(0),
    m_currRegion(0)
{
    m_numTempRegions = regionPts.size();
    // Do a shallow copy of the pointers. From now on, we will
    // own these pointers and be responsible for deleting them.
    m_regionPts = regionPts;
    m_lowerTempBounds.resize(m_numTempRegions);
    m_lowT = m_regionPts[0]->minTemp();
    m_highT = m_regionPts[m_numTempRegions-1]->maxTemp();
    m_Pref = m_regionPts[0]->refPressure();
    m_index = m_regionPts[0]->speciesIndex();
    for (size_t i = 0; i < m_numTempRegions; i++) {
        m_lowerTempBounds[i] = m_regionPts[i]->minTemp();
        if (m_regionPts[i]->speciesIndex() != m_index) {
            throw CanteraError("Nasa9PolyMultiTempRegion::Nasa9PolyMultiTempRegion",
                               "m_index inconsistency");
        }
        if (fabs(m_regionPts[i]->refPressure() - m_Pref) > 0.0001) {
            throw CanteraError("Nasa9PolyMultiTempRegion::Nasa9PolyMultiTempRegion",
                               "refPressure inconsistency");
        }
        if (i > 0) {
            if (m_lowerTempBounds[i-1] >= m_lowerTempBounds[i]) {
                throw CanteraError("Nasa9PolyMultiTempRegion::Nasa9PolyMultiTempRegion",
                                   "minTemp bounds inconsistency");
            }
            if (fabs(m_regionPts[i-1]->maxTemp() - m_lowerTempBounds[i]) > 0.0001) {
                throw CanteraError("Nasa9PolyMultiTempRegion::Nasa9PolyMultiTempRegion",
                                   "Temp bounds inconsistency");
            }
        }
    }
}

Nasa9PolyMultiTempRegion::Nasa9PolyMultiTempRegion(const Nasa9PolyMultiTempRegion& b) :
    SpeciesThermoInterpType(b),
    m_numTempRegions(b.m_numTempRegions),
    m_lowerTempBounds(b.m_lowerTempBounds),
    m_currRegion(b.m_currRegion)
{
    m_regionPts.resize(m_numTempRegions);
    for (size_t i = 0; i < m_numTempRegions; i++) {
        Nasa9Poly1* dptr = b.m_regionPts[i];
        m_regionPts[i] = new Nasa9Poly1(*dptr);
    }
}

Nasa9PolyMultiTempRegion&
Nasa9PolyMultiTempRegion::operator=(const Nasa9PolyMultiTempRegion& b)
{
    if (&b != this) {
        SpeciesThermoInterpType::operator=(b);
        for (size_t i = 0; i < m_numTempRegions; i++) {
            delete m_regionPts[i];
            m_regionPts[i] = 0;
        }
        m_numTempRegions = b.m_numTempRegions;
        m_lowerTempBounds = b.m_lowerTempBounds;
        m_currRegion = b.m_currRegion;
        m_regionPts.resize(m_numTempRegions);
        for (size_t i = 0; i < m_numTempRegions; i++) {
            m_regionPts[i] = new Nasa9Poly1(*(b.m_regionPts[i]));
        }
    }
    return *this;
}

Nasa9PolyMultiTempRegion::~Nasa9PolyMultiTempRegion()
{
    for (size_t i = 0; i < m_numTempRegions; i++) {
        delete m_regionPts[i];
        m_regionPts[i] = 0;
    }
}

SpeciesThermoInterpType*
Nasa9PolyMultiTempRegion::duplMyselfAsSpeciesThermoInterpType() const
{
    return new Nasa9PolyMultiTempRegion(*this);
}

int Nasa9PolyMultiTempRegion::reportType() const
{
    return NASA9MULTITEMP;
}

void Nasa9PolyMultiTempRegion::updateTemperaturePoly(double T, double* T_poly) const
{
    T_poly[0]  = T;
    T_poly[1]  = T * T;
    T_poly[2]  = T_poly[1] * T;
    T_poly[3]  = T_poly[2] * T;
    T_poly[4]  = 1.0 / T;
    T_poly[5]  = T_poly[4] / T;
    T_poly[6]  = std::log(T);
}

void Nasa9PolyMultiTempRegion::updateProperties(const doublereal* tt,
        doublereal* cp_R,
        doublereal* h_RT,
        doublereal* s_R) const
{
    // Let's put some additional debugging here.
    // This is an external routine
#ifdef DEBUG_HKM
    double temp = tt[0];
    if (temp < m_regionPts[m_currRegion]->minTemp()) {
        if (m_currRegion != 0) {
            throw CanteraError("Nasa9PolyMultiTempRegion::updateProperties",
                               "region problem");
        }
    }
    if (temp > m_regionPts[m_currRegion]->maxTemp()) {
        if (m_currRegion != m_numTempRegions - 1) {
            throw CanteraError("Nasa9PolyMultiTempRegion::updateProperties",
                               "region problem");
        }
    }
#endif
    (m_regionPts[m_currRegion])->updateProperties(tt, cp_R, h_RT, s_R);
}

void Nasa9PolyMultiTempRegion::updatePropertiesTemp(const doublereal temp,
        doublereal* cp_R, doublereal* h_RT,
        doublereal* s_R) const
{
    double tPoly[7];
    updateTemperaturePoly(temp, tPoly);
    // Now find the region
    m_currRegion = 0;
    for (size_t i = 1; i < m_numTempRegions; i++) {
        if (temp < m_lowerTempBounds[i]) {
            break;
        }
        m_currRegion++;
    }

    updateProperties(tPoly, cp_R, h_RT, s_R);
}

void Nasa9PolyMultiTempRegion::reportParameters(size_t& n, int& type,
        doublereal& tlow, doublereal& thigh,
        doublereal& pref,
        doublereal* const coeffs) const
{
    n = m_index;
    type = NASA9MULTITEMP;
    tlow = m_lowT;
    thigh = m_highT;
    pref = m_Pref;
    double ctmp[12];
    coeffs[0] = double(m_numTempRegions);
    int index = 1;
    size_t n_tmp = 0;
    int type_tmp = 0;
    double pref_tmp = 0.0;
    for (size_t iReg = 0; iReg < m_numTempRegions; iReg++) {
        m_regionPts[iReg]->reportParameters(n_tmp, type_tmp,
                                            coeffs[index], coeffs[index+1],
                                            pref_tmp, ctmp);
        for (int i = 0; i < 9; i++) {
            coeffs[index+2+i] = ctmp[3+i];
        }
        index += 11;
    }

}

void Nasa9PolyMultiTempRegion::modifyParameters(doublereal* coeffs)
{
    int index = 3;
    for (size_t iReg = 0; iReg < m_numTempRegions; iReg++) {
        m_regionPts[iReg]->modifyParameters(coeffs + index);
        index += 11;
    }
}

}
<commit_msg>Fix Nasa9PolyMultiTempRegion::updateProperties to use the correct polynomial<commit_after>/**
 *  @file Nasa9PolyMultiTempRegion.cpp
 *  Definitions for a single-species standard state object derived
 *  from \link Cantera::SpeciesThermoInterpType
 *    SpeciesThermoInterpType\endlink  based
 *  on the NASA 9 coefficient temperature polynomial form
 *  applied to one temperature region
 *  (see \ref spthermo and class
 *   \link Cantera::Nasa9Poly1 Nasa9Poly1\endlink).
 *
 *  This parameterization has one NASA temperature region.
 */
// Copyright 2007  Sandia National Laboratories

#include "cantera/base/ctexceptions.h"
#include "cantera/thermo/Nasa9PolyMultiTempRegion.h"

using namespace std;

namespace Cantera
{
Nasa9PolyMultiTempRegion::Nasa9PolyMultiTempRegion() :
    m_numTempRegions(0),
    m_currRegion(0)
{
}

Nasa9PolyMultiTempRegion::Nasa9PolyMultiTempRegion(vector<Nasa9Poly1*>& regionPts) :
    m_numTempRegions(0),
    m_currRegion(0)
{
    m_numTempRegions = regionPts.size();
    // Do a shallow copy of the pointers. From now on, we will
    // own these pointers and be responsible for deleting them.
    m_regionPts = regionPts;
    m_lowerTempBounds.resize(m_numTempRegions);
    m_lowT = m_regionPts[0]->minTemp();
    m_highT = m_regionPts[m_numTempRegions-1]->maxTemp();
    m_Pref = m_regionPts[0]->refPressure();
    m_index = m_regionPts[0]->speciesIndex();
    for (size_t i = 0; i < m_numTempRegions; i++) {
        m_lowerTempBounds[i] = m_regionPts[i]->minTemp();
        if (m_regionPts[i]->speciesIndex() != m_index) {
            throw CanteraError("Nasa9PolyMultiTempRegion::Nasa9PolyMultiTempRegion",
                               "m_index inconsistency");
        }
        if (fabs(m_regionPts[i]->refPressure() - m_Pref) > 0.0001) {
            throw CanteraError("Nasa9PolyMultiTempRegion::Nasa9PolyMultiTempRegion",
                               "refPressure inconsistency");
        }
        if (i > 0) {
            if (m_lowerTempBounds[i-1] >= m_lowerTempBounds[i]) {
                throw CanteraError("Nasa9PolyMultiTempRegion::Nasa9PolyMultiTempRegion",
                                   "minTemp bounds inconsistency");
            }
            if (fabs(m_regionPts[i-1]->maxTemp() - m_lowerTempBounds[i]) > 0.0001) {
                throw CanteraError("Nasa9PolyMultiTempRegion::Nasa9PolyMultiTempRegion",
                                   "Temp bounds inconsistency");
            }
        }
    }
}

Nasa9PolyMultiTempRegion::Nasa9PolyMultiTempRegion(const Nasa9PolyMultiTempRegion& b) :
    SpeciesThermoInterpType(b),
    m_numTempRegions(b.m_numTempRegions),
    m_lowerTempBounds(b.m_lowerTempBounds),
    m_currRegion(b.m_currRegion)
{
    m_regionPts.resize(m_numTempRegions);
    for (size_t i = 0; i < m_numTempRegions; i++) {
        Nasa9Poly1* dptr = b.m_regionPts[i];
        m_regionPts[i] = new Nasa9Poly1(*dptr);
    }
}

Nasa9PolyMultiTempRegion&
Nasa9PolyMultiTempRegion::operator=(const Nasa9PolyMultiTempRegion& b)
{
    if (&b != this) {
        SpeciesThermoInterpType::operator=(b);
        for (size_t i = 0; i < m_numTempRegions; i++) {
            delete m_regionPts[i];
            m_regionPts[i] = 0;
        }
        m_numTempRegions = b.m_numTempRegions;
        m_lowerTempBounds = b.m_lowerTempBounds;
        m_currRegion = b.m_currRegion;
        m_regionPts.resize(m_numTempRegions);
        for (size_t i = 0; i < m_numTempRegions; i++) {
            m_regionPts[i] = new Nasa9Poly1(*(b.m_regionPts[i]));
        }
    }
    return *this;
}

Nasa9PolyMultiTempRegion::~Nasa9PolyMultiTempRegion()
{
    for (size_t i = 0; i < m_numTempRegions; i++) {
        delete m_regionPts[i];
        m_regionPts[i] = 0;
    }
}

SpeciesThermoInterpType*
Nasa9PolyMultiTempRegion::duplMyselfAsSpeciesThermoInterpType() const
{
    return new Nasa9PolyMultiTempRegion(*this);
}

int Nasa9PolyMultiTempRegion::reportType() const
{
    return NASA9MULTITEMP;
}

void Nasa9PolyMultiTempRegion::updateTemperaturePoly(double T, double* T_poly) const
{
    T_poly[0]  = T;
    T_poly[1]  = T * T;
    T_poly[2]  = T_poly[1] * T;
    T_poly[3]  = T_poly[2] * T;
    T_poly[4]  = 1.0 / T;
    T_poly[5]  = T_poly[4] / T;
    T_poly[6]  = std::log(T);
}

void Nasa9PolyMultiTempRegion::updateProperties(const doublereal* tt,
        doublereal* cp_R,
        doublereal* h_RT,
        doublereal* s_R) const
{
    m_currRegion = 0;
    for (size_t i = 1; i < m_numTempRegions; i++) {
        if (tt[0] < m_lowerTempBounds[i]) {
            break;
        }
        m_currRegion++;
    }

    m_regionPts[m_currRegion]->updateProperties(tt, cp_R, h_RT, s_R);
}

void Nasa9PolyMultiTempRegion::updatePropertiesTemp(const doublereal temp,
        doublereal* cp_R, doublereal* h_RT,
        doublereal* s_R) const
{
    // Now find the region
    m_currRegion = 0;
    for (size_t i = 1; i < m_numTempRegions; i++) {
        if (temp < m_lowerTempBounds[i]) {
            break;
        }
        m_currRegion++;
    }

    m_regionPts[m_currRegion]->updatePropertiesTemp(temp, cp_R, h_RT, s_R);
}

void Nasa9PolyMultiTempRegion::reportParameters(size_t& n, int& type,
        doublereal& tlow, doublereal& thigh,
        doublereal& pref,
        doublereal* const coeffs) const
{
    n = m_index;
    type = NASA9MULTITEMP;
    tlow = m_lowT;
    thigh = m_highT;
    pref = m_Pref;
    double ctmp[12];
    coeffs[0] = double(m_numTempRegions);
    int index = 1;
    size_t n_tmp = 0;
    int type_tmp = 0;
    double pref_tmp = 0.0;
    for (size_t iReg = 0; iReg < m_numTempRegions; iReg++) {
        m_regionPts[iReg]->reportParameters(n_tmp, type_tmp,
                                            coeffs[index], coeffs[index+1],
                                            pref_tmp, ctmp);
        for (int i = 0; i < 9; i++) {
            coeffs[index+2+i] = ctmp[3+i];
        }
        index += 11;
    }

}

void Nasa9PolyMultiTempRegion::modifyParameters(doublereal* coeffs)
{
    int index = 3;
    for (size_t iReg = 0; iReg < m_numTempRegions; iReg++) {
        m_regionPts[iReg]->modifyParameters(coeffs + index);
        index += 11;
    }
}

}
<|endoftext|>


<commit_before>#include "SoundBuffer.h"
#include "WtsAudio.h"

#include <cmath>
#include <QFileInfo>

#include <sndfile.hh>

using namespace WTS;

SoundBuffer::SoundBuffer()
    : m_name("scratch")
    , m_saved(true)
    , m_writePos(0)
    , m_readPos(0)
    , m_normGain(1)
    , m_gain(1)
{
    setRange(0,0);
}

SoundBuffer::SoundBuffer(qint64 sampleCount)
    : m_name("scratch")
    , m_saved(true)
    , m_data(sampleCount, 0)
    , m_writePos(0)
    , m_readPos(0)
    , m_normGain(1)
    , m_gain(1)
{
    setRange(0,sampleCount);
}

SoundBuffer::SoundBuffer(const QString& name, const SoundBuffer& other, qint64 sampleCount)
    : m_name(name)
    , m_saved(false)
    , m_data(other.m_data)
    , m_writePos(0)
    , m_readPos(0)
    , m_normGain(1)
    , m_gain(1)
{
    if (sampleCount && sampleCount != other.sampleCount())
        m_data.resize(sampleCount);
    setRange(0,sampleCount);
}

SoundBuffer& SoundBuffer::operator= (const SoundBuffer& other)
{
    m_data = other.m_data;
    m_name = other.m_name;
    m_saved = other.m_saved;
    m_writePos = 0;
    m_readPos = 0;
    m_range[0] = other.m_range[0];
    m_range[1] = other.m_range[1];
    m_normGain = other.m_normGain;
    m_gain = other.m_gain;
    return *this;
}

void SoundBuffer::save(const QString& path)
{
    if (m_saved)
        return;

    qDebug() << "Save sample to" << path;
    { // block to ensure file is closed by the moment we ask its modification time
        SndfileHandle snd(qPrintable(path),SFM_WRITE,
                SF_FORMAT_WAV | SF_FORMAT_FLOAT,
                1, // channel
                WtsAudio::samplingRate());

        snd.writef(m_data.data(),m_data.size());
    }
    m_timestamp = QFileInfo(path).lastModified();
    m_saved = true;
}

void SoundBuffer::load(const QString& path)
{
    // load either wav or raw
    if (path.contains(QRegExp("\\.wav$")) && QFile(path).exists()) {
        // load wav
        SndfileHandle snd(qPrintable(path));
        m_data.resize(snd.frames());
        snd.readf(m_data.data(),m_data.size());
        // only samples read from wav files are considered saved
        m_saved = true;
    } else {
        // load raw
        QString rawpath(path);
        rawpath.replace(QRegExp("[^\\.]+$"),"raw");
        qDebug() << "Upgrading sample from " << rawpath;
        QFile file(rawpath);

        FileNotFoundError::test(file);

        file.open(QFile::ReadOnly);
        int64_t sampleCount = file.size() / sizeof(float);
        m_data.resize(sampleCount);
        file.read(reinterpret_cast<char *>(m_data.data()),
                sampleCount*sizeof(float));
        file.close();
    }

    m_readPos = 0;
    m_writePos = 0;
    m_name = QFileInfo(path).fileName();
    m_timestamp = QFileInfo(path).lastModified();
}

bool SoundBuffer::maybeReload(const QString& path)
{
    if (QFileInfo(path).lastModified() > m_timestamp) {
        qDebug() << "Sample " << m_name << " has changed on disk";

        qint64 old_length = m_data.size();

        load(path);
        /*
         * if length has changed - select all
         */
        if (m_data.size() != old_length) {
            m_range[0] = 0;
            m_range[1] = m_data.size()-1;
        }
        return true;
    } else
        return false;
}

float* SoundBuffer::floatAt(qint64 pos)
{
    return m_data.data() + pos;
}

const float* SoundBuffer::floatAt(qint64 pos) const
{
    return m_data.constData() + pos;
}

void SoundBuffer::paste(const SoundBuffer * other)
{
    qint64 pasteSize = std::min(sampleCount() - m_writePos, other->sampleCount());
    qCopy( other->m_data.begin(), other->m_data.begin() + pasteSize, m_data.begin() );
    m_writePos += pasteSize;
}

float* SoundBuffer::chunkToWrite(qint64& size) {
    size = std::min(size, sampleCount() - m_writePos);
    float * chunk = floatAt(m_writePos);
    m_writePos += size;
    return chunk;
}

qint64 SoundBuffer::duration() const
{
    return WtsAudio::sampleCountToMs(m_data.size());
}

void SoundBuffer::initGains()
{
    float peak = 0.0;
    foreach(float v, m_data) {
        if (fabs(v) > peak) {
            peak = v;
        }
    }
    m_normGain = 1.0 / peak;
    m_gain = peak;
    // What?
}

float WTS::SoundBuffer::draw(QPixmap& surface, bool recording, float scaleMax)
{
    QPainter painter(&surface);
    painter.setPen(QColor(0,0,0,100));
    painter.fillRect(0,0,surface.width(),surface.height(), color() );
    int midY = surface.height()/2;

    qint64 stride = 1;
    const float * val = floatAt(0);
    qint64 lineCount =
            std::min((qint64)surface.width(),
                     recording ? m_writePos : sampleCount());
    QVector<float> Y(lineCount, 0.0);

    if (recording) {
        val = floatAt(m_writePos - lineCount);
    } else {
        // show the whole thing
        stride = sampleCount() / lineCount;
    }

    for(int x = 0; x<lineCount; ++x) {
        Y[x] = val[x*stride];
        for(int i=1; i<stride; ++i) {
            Y[x] = std::max(Y[x], (float)fabs(val[x*stride+i]));
        }
        scaleMax = std::max(Y[x],scaleMax);
    }

    for(int x = 0; x<lineCount; ++x) {
        int y1 = midY + (0.45 * (Y[x]/scaleMax) * (float)surface.height());
        int y2 = midY - (0.45 * (Y[x]/scaleMax) * (float)surface.height());
        painter.drawLine(x, y1, x, y2);
    }

    painter.drawLine(lineCount, midY, surface.width(), midY);
    return scaleMax;
}
<commit_msg>no more raw support<commit_after>#include "SoundBuffer.h"
#include "WtsAudio.h"

#include <cmath>
#include <QFileInfo>

#include <sndfile.hh>

using namespace WTS;

SoundBuffer::SoundBuffer()
    : m_name("scratch")
    , m_saved(true)
    , m_writePos(0)
    , m_readPos(0)
    , m_normGain(1)
    , m_gain(1)
{
    setRange(0,0);
}

SoundBuffer::SoundBuffer(qint64 sampleCount)
    : m_name("scratch")
    , m_saved(true)
    , m_data(sampleCount, 0)
    , m_writePos(0)
    , m_readPos(0)
    , m_normGain(1)
    , m_gain(1)
{
    setRange(0,sampleCount);
}

SoundBuffer::SoundBuffer(const QString& name, const SoundBuffer& other, qint64 sampleCount)
    : m_name(name)
    , m_saved(false)
    , m_data(other.m_data)
    , m_writePos(0)
    , m_readPos(0)
    , m_normGain(1)
    , m_gain(1)
{
    if (sampleCount && sampleCount != other.sampleCount())
        m_data.resize(sampleCount);
    setRange(0,sampleCount);
}

SoundBuffer& SoundBuffer::operator= (const SoundBuffer& other)
{
    m_data = other.m_data;
    m_name = other.m_name;
    m_saved = other.m_saved;
    m_writePos = 0;
    m_readPos = 0;
    m_range[0] = other.m_range[0];
    m_range[1] = other.m_range[1];
    m_normGain = other.m_normGain;
    m_gain = other.m_gain;
    return *this;
}

void SoundBuffer::save(const QString& path)
{
    if (m_saved)
        return;

    qDebug() << "Save sample to" << path;
    { // block to ensure file is closed by the moment we ask its modification time
        SndfileHandle snd(qPrintable(path),SFM_WRITE,
                SF_FORMAT_WAV | SF_FORMAT_FLOAT,
                1, // channel
                WtsAudio::samplingRate());

        snd.writef(m_data.data(),m_data.size());
    }
    m_timestamp = QFileInfo(path).lastModified();
    m_saved = true;
}

void SoundBuffer::load(const QString& path)
{
    if (QFile(path).exists()) {
        SndfileHandle snd(qPrintable(path));
        m_data.resize(snd.frames());
        snd.readf(m_data.data(),m_data.size());
        m_saved = true;
    }

    m_readPos = 0;
    m_writePos = 0;
    m_name = QFileInfo(path).fileName();
    m_timestamp = QFileInfo(path).lastModified();
}

bool SoundBuffer::maybeReload(const QString& path)
{
    if (QFileInfo(path).lastModified() > m_timestamp) {
        qDebug() << "Sample " << m_name << " has changed on disk";

        qint64 old_length = m_data.size();

        load(path);
        /*
         * if length has changed - select all
         */
        if (m_data.size() != old_length) {
            m_range[0] = 0;
            m_range[1] = m_data.size()-1;
        }
        return true;
    } else
        return false;
}

float* SoundBuffer::floatAt(qint64 pos)
{
    return m_data.data() + pos;
}

const float* SoundBuffer::floatAt(qint64 pos) const
{
    return m_data.constData() + pos;
}

void SoundBuffer::paste(const SoundBuffer * other)
{
    qint64 pasteSize = std::min(sampleCount() - m_writePos, other->sampleCount());
    qCopy( other->m_data.begin(), other->m_data.begin() + pasteSize, m_data.begin() );
    m_writePos += pasteSize;
}

float* SoundBuffer::chunkToWrite(qint64& size) {
    size = std::min(size, sampleCount() - m_writePos);
    float * chunk = floatAt(m_writePos);
    m_writePos += size;
    return chunk;
}

qint64 SoundBuffer::duration() const
{
    return WtsAudio::sampleCountToMs(m_data.size());
}

void SoundBuffer::initGains()
{
    float peak = 0.0;
    foreach(float v, m_data) {
        if (fabs(v) > peak) {
            peak = v;
        }
    }
    m_normGain = 1.0 / peak;
    m_gain = peak;
    // What?
}

float WTS::SoundBuffer::draw(QPixmap& surface, bool recording, float scaleMax)
{
    QPainter painter(&surface);
    painter.setPen(QColor(0,0,0,100));
    painter.fillRect(0,0,surface.width(),surface.height(), color() );
    int midY = surface.height()/2;

    qint64 stride = 1;
    const float * val = floatAt(0);
    qint64 lineCount =
            std::min((qint64)surface.width(),
                     recording ? m_writePos : sampleCount());
    QVector<float> Y(lineCount, 0.0);

    if (recording) {
        val = floatAt(m_writePos - lineCount);
    } else {
        // show the whole thing
        stride = sampleCount() / lineCount;
    }

    for(int x = 0; x<lineCount; ++x) {
        Y[x] = val[x*stride];
        for(int i=1; i<stride; ++i) {
            Y[x] = std::max(Y[x], (float)fabs(val[x*stride+i]));
        }
        scaleMax = std::max(Y[x],scaleMax);
    }

    for(int x = 0; x<lineCount; ++x) {
        int y1 = midY + (0.45 * (Y[x]/scaleMax) * (float)surface.height());
        int y2 = midY - (0.45 * (Y[x]/scaleMax) * (float)surface.height());
        painter.drawLine(x, y1, x, y2);
    }

    painter.drawLine(lineCount, midY, surface.width(), midY);
    return scaleMax;
}
<|endoftext|>


<commit_before>/*
 * This file is distributed under the terms in the attached LICENSE file.
 * If you do not find this file, copies can be found by writing to:
 * Intel Research Berkeley, 2150 Shattuck Avenue, Suite 1300,
 * Berkeley, CA, 94704.  Attention:  Intel License Inquiry.
 * Or
 * UC Berkeley EECS Computer Science Division, 387 Soda Hall #1776,
 * Berkeley, CA,  94707. Attention: P2 Group.
 *
 * DESCRIPTION: Element which simply prints any tuple that passes
 * through it.
 */

#include "p2.h"
#include "loop.h"
#include "udp.h"
#include "dDuplicateConservative.h"
#include "overlogCompiler.h"
#include "dataflowInstaller.h"
#include "timedPullPush.h"
#include "queue.h"
#include "ol_lexer.h"
#include "ol_context.h"
#include "plmb_confgen.h"
#include "val_str.h"
#include <iostream>

P2::P2(string hostname, string port, uint tc)
  : _plumber(new Plumber()), _id(hostname+":"+port), _transport_conf(tc)
{
  eventLoopInitialize();
  Py_Initialize();
  boost::python::object
    parser(boost::python::handle<>
           (boost::python::borrowed(PyImport_ImportModule("dfparser"))));
  _parser = parser;
  install("dataflow", stub(hostname, port));
  _tupleSourceInterface = dynamic_cast<TupleSourceInterface*>(
    _plumber->dataflow("P2")->find("tupleSourceInterface")->element().get());
  _plumber->toDot("p2.dot");

  Plumber::DataflowEditPtr edit = _plumber->new_dataflow_edit("P2");
  ElementSpecPtr dDemux      = edit->find("dDemux");
  ElementSpecPtr dRoundRobin = edit->find("dRoundRobin");
  ElementSpecPtr qinput      = edit->addElement(
    ElementPtr(new Queue("demuxQueue_overlogInstall", 100)));
  ElementSpecPtr qoutput     = edit->addElement(
    ElementPtr(new Queue("output_queue", 100)));
  ElementSpecPtr pullPush    = edit->addElement(
    ElementPtr(new TimedPullPush("demuxTimedPullPush_overlogInstall", 0)));
  ElementSpecPtr duplicator  = edit->addElement(
    ElementPtr(new DDuplicateConservative("dc_overlogInstall", 1)));
  ElementSpecPtr overlogCompiler = edit->addElement(
    ElementPtr(new OverlogCompiler("overlogCompiler", _plumber, _id, "P2")));
  ElementSpecPtr dataflowInstaller = edit->addElement(
    ElementPtr(new DataflowInstaller("dataflowInstaller", _plumber, _parser)));

  edit->hookUp(dDemux, dDemux->add_output(Val_Str::mk("overlogInstall")), qinput, 0);
  edit->hookUp(qinput, 0, pullPush, 0);
  edit->hookUp(pullPush, 0, duplicator, 0);
  edit->hookUp(duplicator, 0, overlogCompiler, 0);
  edit->hookUp(overlogCompiler, 0, dataflowInstaller, 0);
  edit->hookUp(dataflowInstaller, 0, qoutput, 0);
  edit->hookUp(qoutput, 0, dRoundRobin, dRoundRobin->add_input());
  if (_plumber->install(edit) < 0) {
    std::cerr << "OVERLOG AND DATAFLOW INSTALLER FAILURE" << std::endl;
    exit(1);
  }
#ifdef DEBUG
  _plumber->toDot("p2.dot");
#endif
}

int P2::install(string type, string program)
{
  if (type == string("overlog")) {
    ostringstream script;
    compileOverlog(program, script);
    program = script.str();
    type = "dataflow";
  }

  if (type == string("dataflow")) {
    _parser.attr("clear")();
    boost::python::tuple result =
      boost::python::extract<boost::python::tuple>(
        _parser.attr("compile")(_plumber, program));
    boost::python::dict dataflows =
      boost::python::extract<boost::python::dict>(result[0]);
    boost::python::list edits     =
      boost::python::extract<boost::python::list>(result[1]);

    int ndataflows = boost::python::extract<int>(dataflows.attr("__len__")());
    int nedits     = boost::python::extract<int>(edits.attr("__len__")());

    if (ndataflows) {
      boost::python::tuple t = dataflows.popitem();
      t[1].attr("eval_dataflow")();
      Plumber::DataflowPtr d =
        boost::python::extract<Plumber::DataflowPtr>(t[1].attr("conf"));
      if (_plumber->install(d) < 0) {
        std::cerr << "DATAFLOW INSTALLATION FAILURE" << std::endl;
        return -1;
      }
    }
    if (nedits) {
      edits[0].attr("eval_dataflow")();
      Plumber::DataflowEditPtr e =
        boost::python::extract<Plumber::DataflowEditPtr>(edits[0].attr("conf"));
      if (_plumber->install(e) < 0) {
        std::cerr << "EDIT INSTALLATION FAILURE" << std::endl;
        return -1;
      }
    }
#ifdef DEBUG
    _plumber->toDot("p2.dot");
#endif
  }
  return 0;
}

void P2::run()
{
  eventLoop();
}

P2::CallbackHandlePtr P2::subscribe(string tupleName, cb_tp callback)
{
  int port = -1;	// The port that the listener sits on
  // Create a new edit
  Plumber::DataflowEditPtr edit = _plumber->new_dataflow_edit("P2");
  ElementSpecPtr listener =
    edit->addElement(ElementPtr(new TupleListener("listener_"+tupleName, callback)));

  // The planner creates the duplicator name, see if one already exists
  ElementSpecPtr duplicator = edit->find("dc_"+tupleName);
  if (!duplicator) {
    /** We want to listen for something that has no rule strand
     *  We first need to register it with the demux then hang a duplicator off of the demux
     *  A rule strand that is installed later, and assumes the tuple name is an event,
     *  will find this duplicator and install the strand properly. At this point this
     *  event can no longer be materialized */
    ElementSpecPtr ddemux   = edit->find("dDemux");
    ElementSpecPtr queue    = edit->addElement(
      ElementPtr(new Queue("demuxQueue_"+tupleName, 100)));
    ElementSpecPtr pullPush = edit->addElement(
      ElementPtr(new TimedPullPush("demuxTimedPullPush_"+tupleName, 0)));
    duplicator = edit->addElement(
      ElementPtr(new DDuplicateConservative("dc_"+tupleName, 0)));

    // Hook everything up except duplicator output
    edit->hookUp(ddemux, ddemux->add_output(Val_Str::mk(tupleName)), queue, 0);
    edit->hookUp(queue, 0, pullPush, 0);
    edit->hookUp(pullPush, 0, duplicator, 0);
  }
  // Not hookup the listener to the duplicator output
  port = duplicator->add_output();
  edit->hookUp(duplicator, port, listener, 0);
  if (_plumber->install(edit) < 0) {
    std::cerr << "ERROR: Couldn't install listener" << std::endl;
    return P2::CallbackHandlePtr();
  }
#ifdef DEBUG
  _plumber->toDot("p2.dot");
#endif
  // Return a handle to the caller for unsubscribing to the listener.
  return P2::CallbackHandlePtr(new P2::CallbackHandle(tupleName, port));
}

void P2::unsubscribe(P2::CallbackHandlePtr handle)
{
  if (!handle || handle->_valid == false) {
    std::cerr << "ERROR: invalid callback handle." << std::endl;
  }
  else {
    // Invalidate the handle
    handle->_valid = false;
  }
  unsigned port    = handle->_port;
  string tupleName = handle->_name;

  /* All this routine does it take out an edit, uses it to locate the
   * duplicator, and removes the port. */
  Plumber::DataflowEditPtr edit = _plumber->new_dataflow_edit("P2");
  ElementSpecPtr     duplicator = edit->find("dc_"+tupleName);
  if (!duplicator) {
    std::cerr << "ERROR: no listener registered for " << tupleName << std::endl;
    return;
  }
  edit->disconnect_output(duplicator, port);
  if (_plumber->install(edit) < 0) {
    std::cerr << "ERROR: uninstall listener" << std::endl;
    return;
  }

}

int P2::tuple(TuplePtr tp)
{
  /* Using the tupleSourceInterface, attached right before the demux, to
   * inject a tuple into the system. */
  return _tupleSourceInterface->tuple(tp);
}

void P2::compileOverlog(string overlog, std::ostringstream& script) {
  std::istringstream overlog_iss(overlog, std::istringstream::in);
  boost::shared_ptr< OL_Context > ctxt(new OL_Context());
  ctxt->parse_stream(&overlog_iss);

  Plumber::DataflowEditPtr conf = _plumber->new_dataflow_edit("P2");
  Plmb_ConfGen *gen = new Plmb_ConfGen(ctxt.get(), conf, false, false, false,
                                       string("overlogCompiler"), false, script, true);
  gen->createTables(_id);
  gen->configurePlumber(boost::shared_ptr<Udp>(), _id);
}

string P2::stub(string hostname, string port)
{
  ostringstream stub;
  stub << "dataflow P2 { \
           let udp = Udp2(\"udp\"," << port << "); \
           let wrapAroundDemux = Demux(\"wrapAroundSendDemux\", \{Val_Str(\""
                                                                << hostname << ":" << port
                                                                << "\")}, 0); \
           let inputRR = RoundRobin(\"inputRR\", 3); \
           let header  = PelTransform(\"source\", \"$0 pop \\\""
                                      << hostname <<":" << port
                                      << "\\\" pop swallow unbox drop "
                                      << "0 pop 0 pop 0 pop 0 pop 0 pop 0 pop popall\"); ";

  if (_transport_conf & (RELIABLE | RCC | CC | ORDERED)) {
    stub << "let rtt      = RoundTripTimer(\"rtt_timer\"); ";
    stub << "let ackDemux = Demux(\"ackDemux\", {Val_Str(\"ACK\")}, 1); ";
    stub << "let netoutRR = RoundRobin(\"netoutRR\", 2); ";
    stub << "let ack = BasicAck(\"acknowledge\"); ";

    if (_transport_conf & CC) {
      stub << "let cct = CCT(\"cct\"); ";
    }
    else if (_transport_conf & RCC) {
      stub << "let rcct = RateCCT(\"rcct\"); ";
    }

    if (_transport_conf & RELIABLE)  {
      stub << "let rdelv = RDelivery(\"reliable_delivery\"); ";
    }
  }

  stub << "udp-> UnmarshalField(\"unmarshal\", 1) -> \
           PelTransform(\"unRoute\", \"$1 unboxPop\") ->";

  stub << "Defrag(\"defrag\") -> TimedPullPush(\"defrag_pull\", 0) ->";
  if (_transport_conf & (RCC | CC | RELIABLE | ORDERED)) {
    stub << "ackDemux[1] -> ack ->";
  }

  if (_transport_conf & ORDERED) {
    stub << "ODelivery(\"order\") ->";
  }
  else if (_transport_conf & RELIABLE) {
    stub << "DupRemove(\"dupremove\") ->";
  }
  stub << "PelTransform(\"unPackage\", \"$8 unboxPop\")->";

  stub << "Queue -> inputRR -> \
           TimedPullPush(\"pullDriver\", 0)     -> \
           PrintWatch(\"printWatch\", {str}) -> \
           DDemux(\"dDemux\", {value}, 0) ->  \
           Discard(\"discard\"); \
           DRoundRobin(\"dRoundRobin\", 0) -> \
           TimedPullPush(\"rrout_pullPush\", 0) -> \
           wrapAroundDemux -> \
           UnboxField(\"unboxWrapAround\", 1) -> \
           Queue(\"wrapAroundQueue\", 1000) -> \
           [1]inputRR; \
           wrapAroundDemux[1] -> Queue -> \
           header -> \
           Sequence(\"terminal_sequence\", 1) ->";

  /** Send side reliable delivery and congestion control */
  if (_transport_conf & (RELIABLE | RCC | CC | ORDERED)) {
    stub << "rtt ->";
    if (_transport_conf & RELIABLE) {
      stub << "rdelv ->";
    }
    if (_transport_conf & CC) {
      stub << "cct ->";
    }
    else if (_transport_conf & RCC) {
      stub << "rcct ->";
    }
    stub << "netoutRR ->";
  }

   stub << "TimedPullPush(\"ppfrag\", 0) -> Frag(\"fragment\") ->";
   stub << "PelTransform(\"package\", \"$0 pop swallow pop\") -> \
            MarshalField(\"marshalField\", 1)              -> \
            StrToSockaddr(\"addr_conv\", 0)                -> \
            udp;  \
            TupleSourceInterface(\"tupleSourceInterface\") -> \
            Queue(\"injectQueue\",1000)-> [2]inputRR; ";

  /** Ack packet send dataflow */
  if (_transport_conf & (RCC | CC | RELIABLE | ORDERED)) {
    stub << "ack[1] ->";

    if (_transport_conf & RCC) {
      stub << "RateCCR(\"rccr\") ->";
    }
    if (_transport_conf & RELIABLE) {
      stub << "CumulativeAck(\"cack\") ->";
    }
    stub << "[1]netoutRR; ";
  }

  /** Ack packet receive dataflow */
  if (_transport_conf & (RELIABLE | RCC | CC | ORDERED)) {
    stub << "ackDemux ->";
    if (_transport_conf & CC) {
      stub << "[1]cct[1] ->";
    }
    else if (_transport_conf & RCC) {
      stub << "[1]rcct[1] ->";
    }

    if (_transport_conf & RELIABLE) {
      stub << "[1]rdelv[1] ->";
    }
    stub << "[1]rtt; ";
  }

  stub << "}\n.	# END OF DATAFLOW DEFINITION";
  return stub.str();
}
<commit_msg>*** empty log message ***<commit_after>/*
 * This file is distributed under the terms in the attached LICENSE file.
 * If you do not find this file, copies can be found by writing to:
 * Intel Research Berkeley, 2150 Shattuck Avenue, Suite 1300,
 * Berkeley, CA, 94704.  Attention:  Intel License Inquiry.
 * Or
 * UC Berkeley EECS Computer Science Division, 387 Soda Hall #1776,
 * Berkeley, CA,  94707. Attention: P2 Group.
 *
 * DESCRIPTION: Element which simply prints any tuple that passes
 * through it.
 */

#include "p2.h"
#include "loop.h"
#include "udp.h"
#include "dDuplicateConservative.h"
#include "overlogCompiler.h"
#include "dataflowInstaller.h"
#include "timedPullPush.h"
#include "queue.h"
#include "ol_lexer.h"
#include "ol_context.h"
#include "plmb_confgen.h"
#include "val_str.h"
#include <iostream>

P2::P2(string hostname, string port, uint tc)
  : _plumber(new Plumber()), _id(hostname+":"+port), _transport_conf(tc)
{
  eventLoopInitialize();
  Py_Initialize();
  boost::python::object
    parser(boost::python::handle<>
           (boost::python::borrowed(PyImport_ImportModule("dfparser"))));
  _parser = parser;
  install("dataflow", stub(hostname, port));
  _tupleSourceInterface = dynamic_cast<TupleSourceInterface*>(
    _plumber->dataflow("P2")->find("tupleSourceInterface")->element().get());
  _plumber->toDot("p2.dot");

  Plumber::DataflowEditPtr edit = _plumber->new_dataflow_edit("P2");
  ElementSpecPtr dDemux      = edit->find("dDemux");
  ElementSpecPtr dRoundRobin = edit->find("dRoundRobin");
  ElementSpecPtr qinput      = edit->addElement(
    ElementPtr(new Queue("demuxQueue_overlogInstall", 100)));
  ElementSpecPtr qoutput     = edit->addElement(
    ElementPtr(new Queue("output_queue", 100)));
  ElementSpecPtr pullPush    = edit->addElement(
    ElementPtr(new TimedPullPush("demuxTimedPullPush_overlogInstall", 0)));
  ElementSpecPtr duplicator  = edit->addElement(
    ElementPtr(new DDuplicateConservative("dc_overlogInstall", 1)));
  ElementSpecPtr overlogCompiler = edit->addElement(
    ElementPtr(new OverlogCompiler("overlogCompiler", _plumber, _id, "P2")));
  ElementSpecPtr dataflowInstaller = edit->addElement(
    ElementPtr(new DataflowInstaller("dataflowInstaller", _plumber, _parser)));

  edit->hookUp(dDemux, dDemux->add_output(Val_Str::mk("overlogInstall")), qinput, 0);
  edit->hookUp(qinput, 0, pullPush, 0);
  edit->hookUp(pullPush, 0, duplicator, 0);
  edit->hookUp(duplicator, 0, overlogCompiler, 0);
  edit->hookUp(overlogCompiler, 0, dataflowInstaller, 0);
  edit->hookUp(dataflowInstaller, 0, qoutput, 0);
  edit->hookUp(qoutput, 0, dRoundRobin, dRoundRobin->add_input());
  if (_plumber->install(edit) < 0) {
    std::cerr << "OVERLOG AND DATAFLOW INSTALLER FAILURE" << std::endl;
    exit(1);
  }
#ifdef DEBUG
  _plumber->toDot("p2.dot");
#endif
}

int P2::install(string type, string program)
{
  if (type == string("overlog")) {
    ostringstream script;
    compileOverlog(program, script);
    program = script.str();
    type = "dataflow";
  }

  if (type == string("dataflow")) {
    _parser.attr("clear")();
    boost::python::tuple result =
      boost::python::extract<boost::python::tuple>(
        _parser.attr("compile")(_plumber, program));
    boost::python::dict dataflows =
      boost::python::extract<boost::python::dict>(result[0]);
    boost::python::list edits     =
      boost::python::extract<boost::python::list>(result[1]);

    int ndataflows = boost::python::extract<int>(dataflows.attr("__len__")());
    int nedits     = boost::python::extract<int>(edits.attr("__len__")());

    if (ndataflows) {
      boost::python::tuple t = dataflows.popitem();
      t[1].attr("eval_dataflow")();
      Plumber::DataflowPtr d =
        boost::python::extract<Plumber::DataflowPtr>(t[1].attr("conf"));
      if (_plumber->install(d) < 0) {
        std::cerr << "DATAFLOW INSTALLATION FAILURE" << std::endl;
        return -1;
      }
    }
    if (nedits) {
      edits[0].attr("eval_dataflow")();
      Plumber::DataflowEditPtr e =
        boost::python::extract<Plumber::DataflowEditPtr>(edits[0].attr("conf"));
      if (_plumber->install(e) < 0) {
        std::cerr << "EDIT INSTALLATION FAILURE" << std::endl;
        return -1;
      }
    }
#ifdef DEBUG
    _plumber->toDot("p2.dot");
#endif
  }
  return 0;
}

void P2::run()
{
  eventLoop();
}

P2::CallbackHandlePtr P2::subscribe(string tupleName, cb_tp callback)
{
  int port = -1;	// The port that the listener sits on
  // Create a new edit
  Plumber::DataflowEditPtr edit = _plumber->new_dataflow_edit("P2");
  ElementSpecPtr listener =
    edit->addElement(ElementPtr(new TupleListener("listener_"+tupleName, callback)));

  // The planner creates the duplicator name, see if one already exists
  ElementSpecPtr duplicator = edit->find("dc_"+tupleName);
  if (!duplicator) {
    /** We want to listen for something that has no rule strand
     *  We first need to register it with the demux then hang a duplicator off of the demux
     *  A rule strand that is installed later, and assumes the tuple name is an event,
     *  will find this duplicator and install the strand properly. At this point this
     *  event can no longer be materialized */
    ElementSpecPtr ddemux   = edit->find("dDemux");
    ElementSpecPtr queue    = edit->addElement(
      ElementPtr(new Queue("demuxQueue_"+tupleName, 100)));
    ElementSpecPtr pullPush = edit->addElement(
      ElementPtr(new TimedPullPush("demuxTimedPullPush_"+tupleName, 0)));
    duplicator = edit->addElement(
      ElementPtr(new DDuplicateConservative("dc_"+tupleName, 0)));

    // Hook everything up except duplicator output
    edit->hookUp(ddemux, ddemux->add_output(Val_Str::mk(tupleName)), queue, 0);
    edit->hookUp(queue, 0, pullPush, 0);
    edit->hookUp(pullPush, 0, duplicator, 0);
  }
  // Not hookup the listener to the duplicator output
  port = duplicator->add_output();
  edit->hookUp(duplicator, port, listener, 0);
  if (_plumber->install(edit) < 0) {
    std::cerr << "ERROR: Couldn't install listener" << std::endl;
    return P2::CallbackHandlePtr();
  }
#ifdef DEBUG
  _plumber->toDot("p2.dot");
#endif
  // Return a handle to the caller for unsubscribing to the listener.
  return P2::CallbackHandlePtr(new P2::CallbackHandle(tupleName, port));
}

void P2::unsubscribe(P2::CallbackHandlePtr handle)
{
  if (!handle || handle->_valid == false) {
    std::cerr << "ERROR: invalid callback handle." << std::endl;
  }
  else {
    // Invalidate the handle
    handle->_valid = false;
  }
  unsigned port    = handle->_port;
  string tupleName = handle->_name;

  /* All this routine does it take out an edit, uses it to locate the
   * duplicator, and removes the port. */
  Plumber::DataflowEditPtr edit = _plumber->new_dataflow_edit("P2");
  ElementSpecPtr     duplicator = edit->find("dc_"+tupleName);
  if (!duplicator) {
    std::cerr << "ERROR: no listener registered for " << tupleName << std::endl;
    return;
  }
  edit->disconnect_output(duplicator, port);
  if (_plumber->install(edit) < 0) {
    std::cerr << "ERROR: uninstall listener" << std::endl;
    return;
  }

}

int P2::tuple(TuplePtr tp)
{
  /* Using the tupleSourceInterface, attached right before the demux, to
   * inject a tuple into the system. */
  return _tupleSourceInterface->tuple(tp);
}

void P2::compileOverlog(string overlog, std::ostringstream& script) {
  std::istringstream overlog_iss(overlog, std::istringstream::in);
  boost::shared_ptr< OL_Context > ctxt(new OL_Context());
  ctxt->parse_stream(&overlog_iss);

  Plumber::DataflowEditPtr conf = _plumber->new_dataflow_edit("P2");
  Plmb_ConfGen *gen = new Plmb_ConfGen(ctxt.get(), conf, false, false, false,
                                       string("overlogCompiler"), false, script, true);
  gen->createTables(_id);
  gen->configurePlumber(boost::shared_ptr<Udp>(), _id);
}

string P2::stub(string hostname, string port)
{
  ostringstream stub;
  stub << "dataflow P2 { \
           let udp = Udp2(\"udp\"," << port << "); \
           let wrapAroundDemux = Demux(\"wrapAroundSendDemux\", \{Val_Str(\""
                                                                << hostname << ":" << port
                                                                << "\")}, 0); \
           let inputRR = RoundRobin(\"inputRR\", 3); \
           let header  = PelTransform(\"source\", \"$0 pop \\\""
                                      << hostname <<":" << port
                                      << "\\\" pop swallow unbox drop "
                                      << "0 pop 0 pop 0 pop 0 pop 0 pop 0 pop popall\"); ";

  if (_transport_conf & (RELIABLE | RCC | CC | ORDERED)) {
    stub << "let rtt      = RoundTripTimer(\"rtt_timer\"); ";
    stub << "let ackDemux = Demux(\"ackDemux\", {Val_Str(\"ACK\")}, 1); ";
    stub << "let netoutRR = RoundRobin(\"netoutRR\", 2); ";
    stub << "let ack = BasicAck(\"acknowledge\"); ";

    if (_transport_conf & CC) {
      stub << "let cct = CCT(\"cct\"); ";
    }
    else if (_transport_conf & RCC) {
      stub << "let rcct = RateCCT(\"rcct\"); ";
    }

    if (_transport_conf & RELIABLE)  {
      stub << "let rdelv = RDelivery(\"reliable_delivery\"); ";
    }
  }

  stub << "udp-> UnmarshalField(\"unmarshal\", 1) -> \
           PelTransform(\"unRoute\", \"$1 unboxPop\") ->";

  stub << "Defrag(\"defrag\") -> TimedPullPush(\"defrag_pull\", 0) ->";
  if (_transport_conf & (RCC | CC | RELIABLE | ORDERED)) {
    stub << "ackDemux[1] -> ack ->";
  }

  if (_transport_conf & ORDERED) {
    stub << "ODelivery(\"order\") ->";
  }
  else if (_transport_conf & RELIABLE) {
    stub << "DupRemove(\"dupremove\") ->";
  }
  stub << "PelTransform(\"unPackage\", \"$8 unboxPop\")->";

  stub << "Queue -> inputRR -> \
           TimedPullPush(\"pullDriver\", 0)     -> \
           PrintWatch(\"printWatch\", {str}) -> \
           DDemux(\"dDemux\", {value}, 0) ->  \
           Discard(\"discard\"); \
           DRoundRobin(\"dRoundRobin\", 0) -> \
           TimedPullPush(\"rrout_pullPush\", 0) -> \
           wrapAroundDemux -> \
           UnboxField(\"unboxWrapAround\", 1) -> \
           Queue(\"wrapAroundQueue\", 1000) -> \
           [1]inputRR; \
           wrapAroundDemux[1] -> Queue(\"netout_queue\", 1000) -> \
           header -> \
           Sequence(\"terminal_sequence\", 1) ->";

  /** Send side reliable delivery and congestion control */
  if (_transport_conf & (RELIABLE | RCC | CC | ORDERED)) {
    stub << "rtt ->";
    if (_transport_conf & RELIABLE) {
      stub << "rdelv ->";
    }
    if (_transport_conf & CC) {
      stub << "cct ->";
    }
    else if (_transport_conf & RCC) {
      stub << "rcct ->";
    }
    stub << "netoutRR ->";
  }

   stub << "TimedPullPush(\"ppfrag\", 0) -> Frag(\"fragment\") ->";
   stub << "PelTransform(\"package\", \"$0 pop swallow pop\") -> \
            MarshalField(\"marshalField\", 1)              -> \
            StrToSockaddr(\"addr_conv\", 0)                -> \
            udp;  \
            TupleSourceInterface(\"tupleSourceInterface\") -> \
            Queue(\"injectQueue\",1000)-> [2]inputRR; ";

  /** Ack packet send dataflow */
  if (_transport_conf & (RCC | CC | RELIABLE | ORDERED)) {
    stub << "ack[1] ->";

    if (_transport_conf & RCC) {
      stub << "RateCCR(\"rccr\") ->";
    }
    if (_transport_conf & RELIABLE) {
      stub << "CumulativeAck(\"cack\") ->";
    }
    stub << "[1]netoutRR; ";
  }

  /** Ack packet receive dataflow */
  if (_transport_conf & (RELIABLE | RCC | CC | ORDERED)) {
    stub << "ackDemux ->";
    if (_transport_conf & CC) {
      stub << "[1]cct[1] ->";
    }
    else if (_transport_conf & RCC) {
      stub << "[1]rcct[1] ->";
    }

    if (_transport_conf & RELIABLE) {
      stub << "[1]rdelv[1] ->";
    }
    stub << "[1]rtt; ";
  }

  stub << "}\n.	# END OF DATAFLOW DEFINITION";
  return stub.str();
}
<|endoftext|>


<commit_before>/*
 * cli_emulator.cpp
 *
 *  Created on: Sep 20, 2015
 *      Author: anon
 */

#include "arm/ARMArch.h"
#include "arm/ARMEmulator.h"
#include "arm/ARMDisassembler.h"
#include "memory/Memory.h"

#include <string>
#include <cstdint>
#include <iostream>

using namespace std;
using namespace Memory;
using namespace Register;
using namespace Emulator;
using namespace Disassembler;

int main(int argc, char **argv) {
	if (argc < 2) {
		cerr << "Usage: ./%s [thumb|arm] <hex_opcode>" << endl;
		return -1;
	}

	string arg_mode { argv[1] };

	ARMMode mode { ARMMode_ARM };
	if (arg_mode == "thumb") {
		mode = ARMMode_Thumb;
	}

	cout << "Using mode " << (mode == ARMMode_Thumb ? "THUMB" : "ARM") << endl;

	// Create a concrete memory map.
	ConcreteMemory memory { };
	if (!memory.map(0xcafe0000, 0x1000, 0)) {
		cerr << "Failed mapping address." << endl;
		return -1;
	}

	// Set some values.
	uintptr_t address = 0xcafe0000;

	address += memory.write_value(address, 0xe3a02010); // mov r2, #16
	address += memory.write_value(address, 0xe1a0100f); // mov r1, pc
	address += memory.write_value(address, 0xe2811018); // add r1, r1, #24
	address += memory.write_value(address, 0xe3a00001); // mov r0, #1
	address += memory.write_value(address, 0xe3a07004); // mov r7, #4

	// Create an execution context.
	ARMContext context { &memory };
	context.setRegister(ARM_REG_R0, 0);
	context.setRegister(ARM_REG_PC, 0xcafe0000);

	// Create an emulator and link the memory and context
	ARMEmulator emu { &context, &memory, mode };
	emu.start(5);

	return 0;
}
<commit_msg>Simplified cli_emulator<commit_after>/*
 * cli_emulator.cpp
 *
 *  Created on: Sep 20, 2015
 *      Author: anon
 */

#include "arm/ARMArch.h"
#include "arm/ARMEmulator.h"
#include "arm/ARMDisassembler.h"
#include "memory/Memory.h"

#include <string>
#include <cstdint>
#include <iostream>

using namespace std;
using namespace Memory;
using namespace Register;
using namespace Emulator;
using namespace Disassembler;

int main(int argc, char **argv) {
	if (argc < 2) {
		cerr << "Usage: ./%s [thumb|arm] <hex_opcode>" << endl;
		return -1;
	}

	ARMMode mode { ARMMode_ARM };
	if (string(argv[1]) == "thumb") {
		mode = ARMMode_Thumb;
	}

	cout << "Using mode " << (mode == ARMMode_Thumb ? "THUMB" : "ARM") << endl;

	// Create a concrete memory map.
	ConcreteMemory memory { };
	if (!memory.map(0xcafe0000, 0x1000, 0)) {
		cerr << "Failed mapping address." << endl;
		return -1;
	}

	// Set some values.
	uintptr_t address = 0xcafe0000;

	address += memory.write_value(address, 0xe3a02010); // mov r2, #16
	address += memory.write_value(address, 0xe1a0100f); // mov r1, pc
	address += memory.write_value(address, 0xe2811018); // add r1, r1, #24
	address += memory.write_value(address, 0xe3a00001); // mov r0, #1
	address += memory.write_value(address, 0xe3a07004); // mov r7, #4

	// Create an execution context.
	ARMContext context { &memory };
	context.setRegister(ARM_REG_R0, 0);
	context.setRegister(ARM_REG_PC, 0xcafe0000);

	// Create an emulator and link the memory and context
	ARMEmulator emu { &context, &memory, mode };
	emu.start(5);

	return 0;
}
<|endoftext|>