CScript 式に対応するコードを生成するタイミングを遅らせた。定数畳み込み最適化の下準備。
authorIssei Suzuki <issei@issei.org>
Fri Aug 17 00:07:02 2007 +0900 (16 months ago)
changeset 536a4c77df6739a
parent 535f553b71d1c8a
child 5379adeeb27ffe8
CScript 式に対応するコードを生成するタイミングを遅らせた。定数畳み込み最適化の下準備。
.hgignore
tool/src/cscript/code/code.cc
tool/src/cscript/code/cscript_parser.cc
tool/src/cscript/code/cscript_parser.h
tool/src/cscript/code/parser.y
tool/src/cscript/code/stdafx.h
tool/src/cscript/m4/parser.m4
tool/src/cscript/mk/codemak.mak
tool/src/cscript/mk/cscript.mak
tool/src/cscript/mk/target/debug.mak
tool/src/cscript/sample/while.scs
--- a/.hgignore Fri Aug 10 08:33:42 2007 +0900
+++ b/.hgignore Fri Aug 17 00:07:02 2007 +0900
@@ -13,3 +13,4 @@
(^|/)\.depend($|/)
(^|/).*\.core($|/)
(^|/).*\.d($|/)
+(^|/).*\.dis($|/)
--- a/tool/src/cscript/code/code.cc Fri Aug 10 08:33:42 2007 +0900
+++ b/tool/src/cscript/code/code.cc Fri Aug 17 00:07:02 2007 +0900
@@ -102,6 +102,7 @@ vm_taddr_t Code::Impl::_addCodeImmediate
return 0;
}
}
+
if (!m_pmem.empty() && code == INST_shrink) {
vm_tword_opcode_t code = CSCR_VM_TWORD_OPCODE_GET(m_pmem.back());
vm_tword_oprand_t oprand = CSCR_VM_TWORD_OPRAND_GET(m_pmem.back());
--- a/tool/src/cscript/code/cscript_parser.h Fri Aug 10 08:33:42 2007 +0900
+++ b/tool/src/cscript/code/cscript_parser.h Fri Aug 17 00:07:02 2007 +0900
@@ -103,6 +103,51 @@ typedef boost::shared_ptr<IdList> IdList
typedef boost::shared_ptr<IdList> IdListP;
typedef boost::shared_ptr<CastList> CastListP;
+typedef boost::function<void (Comp* comp)> GenCode;
+typedef std::vector<GenCode> GenCodeList;
+typedef boost::shared_ptr<GenCodeList> GenCodeListP;
+
+struct ExpressionInfo
+{
+public:
+ ExpressionInfo();
+ ExpressionInfo(Cast const& c);
+ explicit ExpressionInfo(vm_int_t n, Cast const& c = Cast::INT);
+ explicit ExpressionInfo(vm_float_t f, Cast const& c = Cast::FLOAT);
+ explicit ExpressionInfo(std::string const& s, Cast const& c = Cast::STRING);
+
+ template <typename T> T getVal() const
+ {
+ return boost::any_cast<T>(m_val);
+ }
+
+ bool isConst() const
+ {
+ return m_is_const;
+ }
+
+ void setCast(Cast const& cast)
+ {
+ m_cast = cast;
+ }
+
+ Cast const& getCast() const
+ {
+ return m_cast;
+ }
+
+ void genCode(Comp* comp);
+ void addGenCode(GenCode const& gen);
+ void addGenCode(ExpressionInfo const& other);
+
+private:
+ Cast m_cast;
+ GenCodeList m_gen_code_list;
+ boost::any m_val;
+ bool m_is_const;
+};
+typedef boost::shared_ptr<ExpressionInfo> ExpressionInfoP;
+
class SymbolFunction;
CSCRIPT_NAMESPACE_END
--- a/tool/src/cscript/code/parser.y Fri Aug 10 08:33:42 2007 +0900
+++ b/tool/src/cscript/code/parser.y Fri Aug 17 00:07:02 2007 +0900
@@ -37,6 +37,7 @@
#define yyerror(msg) ((p_lexer->yyerror)(msg))
CSCRIPT_NAMESPACE_USING
+namespace bl = boost::lambda;
CSCRIPT_NAMESPACE_BEGIN
struct CodeGenEntry
@@ -86,6 +87,11 @@ static void _genPUSH(Comp* comp, vm_dwor
comp->genCodeSETHI(hi);
}
+static void _genPushD(Comp* comp, vm_dword_t d)
+{
+ _genPUSH(comp, d);
+}
+
static void _genPUSH(Comp* comp, vm_float_t f)
{
assert(comp != NULL);
@@ -94,12 +100,22 @@ static void _genPUSH(Comp* comp, vm_floa
_genPUSH(comp, u.d);
}
+static void _genPushF(Comp* comp, vm_float_t f)
+{
+ _genPUSH(comp, f);
+}
+
static void _genPUSH(Comp* comp, vm_int_t n)
{
assert(comp != NULL);
union { vm_int_t n; CScript::vm_dword_t d; } u;
u.n = n;
_genPUSH(comp, u.d);
+}
+
+static void _genPushI(Comp* comp, vm_int_t n)
+{
+ _genPUSH(comp, n);
}
static bool _genSYSCALL(Comp* comp, std::string const& id)
@@ -155,14 +171,6 @@ S: /* empty */
S: /* empty */
| node_root
;
-
-node_taddr: { $$ = p_comp->getCodeSize(); }
-
-node_jump_if0: { $$ = p_comp->genCodeJUMP_IF0(); };
-
-node_jump: { $$ = p_comp->genCodeJUMP(); }
-
-node_true: { p_comp->genCodePUSH(1); }
node_root:
node_root_element
@@ -260,7 +268,6 @@ node_typedef:
if (!cast.canUse(D_VAR))
yyerror((std::string("illegal cast type [") + cast.getStr() + "]"));
- namespace bl = boost::lambda;
IdListP& id_list = boost::any_cast<IdListP&>($3);
for (IdList::const_iterator i = id_list->begin(); i != id_list->end(); ++i)
if (p_comp->defineCast(*i, cast) == NULL) {
@@ -404,7 +411,8 @@ node_var0:
break;
}
- Cast const& cast_expr = boost::any_cast<Cast const&>($3);
+ ExpressionInfoP expr = boost::any_cast<ExpressionInfoP>($3);
+ Cast cast_expr = expr->getCast();
if (cast_expr != Cast::ERROR && cast_cur != Cast::ERROR && cast_expr != cast_cur) {
yyerror("cast mismatch");
break;
@@ -414,9 +422,9 @@ node_var0:
CodeGenEntry const* e = NULL;
if (!_getCodeGenEntry(&e, &sym, p_comp, id)) {
yyerror(std::string("undefined variable [" + id + "]"));
- $$ = Cast::ERROR;
break;
}
+ expr->genCode(p_comp);
(p_comp->*(e->gen_store))(sym->getAddr());
p_comp->genCodeSHRINK(cast_cur.getSize());
}
@@ -492,7 +500,6 @@ node_timeline:
} node_when_list {
p_comp->backpatchJUMP(boost::any_cast<vm_taddr_t>($7), p_comp->getCodeSize());
- namespace bl = boost::lambda;
WhenInfoList& wlist = *boost::any_cast<WhenInfoListP&>($8);
std::sort(
wlist.begin(), wlist.end(),
@@ -733,16 +740,18 @@ node_jump_statement:
}
| TOK_RETURN node_expression ';'
{
+ ExpressionInfoP expr = boost::any_cast<ExpressionInfoP>($2);
SymbolFunction const* sym_func = p_comp->getCurrentFunction();
assert(sym_func != NULL);
Cast const cast_func = sym_func->getCast();
- if (cast_func != Cast::ERROR && cast_func != boost::any_cast<Cast const&>($2)) {
+ if (cast_func != Cast::ERROR && cast_func != expr->getCast()) {
yyerror(std::string("return cast mismatch"));
break;
}
SymbolVariable const* sym_ret = p_comp->findLocalVariable(Comp::SYMBOL_RET_VAL);
assert(sym_ret != NULL);
+ expr->genCode(p_comp);
p_comp->genCodeSTORE(sym_ret->getAddr());
p_comp->genCodeLEAVE();
p_comp->genCodeRETURN(sym_func->getParamSize());
@@ -774,18 +783,77 @@ node_jump_statement:
}
;
+node_if_statement:
+ TOK_IF '(' node_conditional_expression ')'
+ {
+ ExpressionInfoP expr = boost::any_cast<ExpressionInfoP>($3);
+ expr->genCode(p_comp);
+ $$ = p_comp->genCodeJUMP_IF0();
+ }
+ node_statement
+ {
+ $$ = $5;
+ }
+ ;
+
node_selection_statement:
- TOK_IF '(' node_conditional_expression ')' node_jump_if0 node_statement
+ node_if_statement
+ /*
+ [expr_cond]
+ jump_if0 exit_if
+ [statement]
+ exit_if:
+ */
{
- p_comp->backpatchJUMP_IF0(boost::any_cast<vm_taddr_t>($5), p_comp->getCodeSize());
+ p_comp->backpatchJUMP_IF0(boost::any_cast<vm_taddr_t>($1), p_comp->getCodeSize());
}
- | TOK_IF '(' node_conditional_expression ')' node_jump_if0 node_statement TOK_ELSE node_jump node_statement
+ | node_if_statement
+ /*
+ [expr_cond]
+ jump_if0 else_statement
+ [statement1]
+ jump exit_if
+ else_statement:
+ [statement2]
+ exit_if:
+ */
+ TOK_ELSE {
+ $$ = p_comp->genCodeJUMP();
+ p_comp->backpatchJUMP_IF0(boost::any_cast<vm_taddr_t>($1), p_comp->getCodeSize());
+ } node_statement {
+ p_comp->backpatchJUMP(boost::any_cast<vm_taddr_t>($3), p_comp->getCodeSize());
+ }
+ | TOK_SWITCH
+ /*
+ [expr]
+ jump L_switch
+ L_case1:
+ [statement1]
+ L_case2:
+ [statement2]
+ jump L_switch_exit ; break
+ L_default:
+ [statement_default]
+ jump L_switch_exit
+ L_switch:
+ L_cond1:
+ dup
+ push [case1]
+ neq
+ jump_if0 L_case1
+ L_cond2:
+ dup
+ push [case2]
+ neq
+ jump_if0 L_case2
+ L_default:
+ jump L_default
+ L_switch_exit:
+ */
+ '(' node_conditional_expression ')'
{
- p_comp->backpatchJUMP_IF0(boost::any_cast<vm_taddr_t>($5), boost::any_cast<vm_taddr_t>($8) + 1);
- p_comp->backpatchJUMP(boost::any_cast<vm_taddr_t>($8), p_comp->getCodeSize());
- }
- | TOK_SWITCH '(' node_conditional_expression ')'
- {
+ ExpressionInfoP expr = boost::any_cast<ExpressionInfoP>($3);
+ expr->genCode(p_comp);
p_comp->beginSwitch();
$$ = p_comp->genCodeJUMP();
}
@@ -799,76 +867,130 @@ node_conditional_expression:
node_conditional_expression:
node_expression
{
- Cast const& cast = boost::any_cast<Cast const&>($1);
- if (cast != Cast::ERROR && cast != Cast::INT)
+ ExpressionInfoP expr = boost::any_cast<ExpressionInfoP>($1);
+ Cast cast = expr->getCast();
+ if (cast != Cast::ERROR && cast != Cast::INT) {
yyerror("`int' cast expected");
+ $$ = ExpressionInfoP(new ExpressionInfo(1));
+ break;
+ }
+
+ $$ = $1;
}
;
-node_conditional_expression_or_empty: /* empty */ { $$ = Cast::ERROR; }
+node_conditional_expression_or_empty: /* empty */
+ { $$ = ExpressionInfoP(new ExpressionInfo()); }
| node_conditional_expression
;
node_expression_or_empty: /* empty */
+ { $$ = ExpressionInfoP(new ExpressionInfo()); }
| node_expression
- {
- p_comp->genCodeSHRINK(boost::any_cast<Cast const&>($1).getSize());
- }
- ;
-
-node_iteration_begin:
- {
- p_comp->beginLoop();
- }
;
node_iteration_statement:
- TOK_WHILE node_iteration_begin node_taddr '(' node_conditional_expression ')' node_jump_if0 node_statement
+ TOK_WHILE
+ /*
+ while_cond:
+ [expr_cond]
+ jump_if0 while_exit
+ [statement]
+ jump while_cond
+ while_exit:
+ */
+ { $$ = p_comp->getCodeSize(); }
+ '(' node_conditional_expression ')' {
+ ExpressionInfoP expr = boost::any_cast<ExpressionInfoP>($4);
+ expr->genCode(p_comp);
+ $$ = p_comp->genCodeJUMP_IF0();
+
+ p_comp->beginLoop();
+ } node_statement {
+ p_comp->genCodeJUMP(boost::any_cast<vm_taddr_t>($2));
+ p_comp->endLoop(boost::any_cast<vm_taddr_t>($2));
+ p_comp->backpatchJUMP_IF0(boost::any_cast<vm_taddr_t>($6), p_comp->getCodeSize());
+ }
+ | TOK_DO
+ /*
+ do_loop:
+ [statement]
+ [expr_cond]
+ test0
+ jump_if0 do_loop
+ */
{
- p_comp->genCodeJUMP(boost::any_cast<vm_taddr_t>($3));
- p_comp->backpatchJUMP_IF0(boost::any_cast<vm_taddr_t>($7), p_comp->getCodeSize());
- p_comp->endLoop(boost::any_cast<vm_taddr_t>($3));
+ p_comp->beginLoop();
+ $$ = p_comp->getCodeSize();
}
- | TOK_DO node_iteration_begin node_taddr node_statement TOK_WHILE node_taddr '(' node_conditional_expression ')' ';'
+ node_statement TOK_WHILE '('
{
+ $$ = p_comp->getCodeSize();
+ }
+ node_conditional_expression ')' ';'
+ {
+ ExpressionInfoP expr = boost::any_cast<ExpressionInfoP>($7);
+ expr->genCode(p_comp);
p_comp->genOprTEST0_I();
- p_comp->genCodeJUMP_IF0(boost::any_cast<vm_taddr_t>($3));
+ p_comp->genCodeJUMP_IF0(boost::any_cast<vm_taddr_t>($2));
+
p_comp->endLoop(boost::any_cast<vm_taddr_t>($6));
}
- | TOK_FOR // 1
- node_iteration_begin // 2
- '(' // 3
- node_expression_or_empty // 4
- ';' // 5
- node_taddr // 6
- node_conditional_expression_or_empty // 7
- ';' // 8
- node_jump_if0 // 9
- node_jump // 10
- node_taddr // 11
- node_expression_or_empty // 12
- node_jump // 13
- ')' // 14
- node_taddr // 15
- node_statement // 16
- node_jump // 17
+ | TOK_FOR // 1
+ /*
+ [expr_init]
+ for_cond:
+ [expr_cond]
+ jump_if0 for_exit
+ [statement]
+ [expr_loop]
+ jump for_cond
+ for_exit:
+
+ */
+ { p_comp->beginLoop(); } // 2
+ '(' // 3
+ node_expression_or_empty // 4
+ ';' // 5
+ node_conditional_expression_or_empty // 6
+ ';' // 7
+ node_expression_or_empty // 8
+ ')' // 9
+ { // 10
+ ExpressionInfoP expr_init = boost::any_cast<ExpressionInfoP>($4);
+ expr_init->genCode(p_comp);
+ p_comp->genCodeSHRINK(expr_init->getCast().getSize());
+ $$ = p_comp->getCodeSize();
+ }
+ { // 11
+ ExpressionInfoP expr_cond = boost::any_cast<ExpressionInfoP>($6);
+ $$ = static_cast<vm_taddr_t>(0);
+ if (expr_cond->getCast() != Cast::ERROR) {
+ expr_cond->genCode(p_comp);
+ $$ = p_comp->genCodeJUMP_IF0();
+ }
+ }
+ node_statement
{
- if (boost::any_cast<Cast const&>($7) == Cast::ERROR)
- p_comp->overrideJUMP_IF0toNOP(boost::any_cast<vm_taddr_t>($9));
- else
- p_comp->backpatchJUMP_IF0(boost::any_cast<vm_taddr_t>($9), p_comp->getCodeSize());
- p_comp->backpatchJUMP(boost::any_cast<vm_taddr_t>($10), boost::any_cast<vm_taddr_t>($15));
- p_comp->backpatchJUMP(boost::any_cast<vm_taddr_t>($13), boost::any_cast<vm_taddr_t>($6));
- p_comp->backpatchJUMP(boost::any_cast<vm_taddr_t>($17), boost::any_cast<vm_taddr_t>($11));
- p_comp->endLoop(boost::any_cast<vm_taddr_t>($11));
+ ExpressionInfoP expr_loop = boost::any_cast<ExpressionInfoP>($8);
+ expr_loop->genCode(p_comp);
+ p_comp->genCodeSHRINK(expr_loop->getCast().getSize());
+ p_comp->genCodeJUMP(boost::any_cast<vm_taddr_t>($10));
+
+ p_comp->endLoop(p_comp->getCodeSize());
+ vm_taddr_t taddr = boost::any_cast<vm_taddr_t>($11);
+ if (taddr > 0)
+ p_comp->backpatchJUMP_IF0(taddr, p_comp->getCodeSize());
}
;
node_expression_statement:
';'
- | node_expression';'
+ | node_expression ';'
{
- p_comp->genCodeSHRINK(boost::any_cast<Cast const&>($1).getSize());
+ ExpressionInfoP expr = boost::any_cast<ExpressionInfoP>($1);
+ expr->genCode(p_comp);
+ p_comp->genCodeSHRINK(expr->getCast().getSize());
}
;
@@ -876,9 +998,16 @@ node_expression:
node_assignment_expression
| node_assignment_expression ',' node_expression
{
- p_comp->genCodeSHRINK(boost::any_cast<Cast const&>($1).getSize());
-
- $$ = $3;
+ ExpressionInfoP expr_l = boost::any_cast<ExpressionInfoP>($1);
+ ExpressionInfoP expr_r = boost::any_cast<ExpressionInfoP>($3);
+ expr_l->addGenCode(bl::bind(
+ &Comp::genCodeSHRINK,
+ bl::_1,
+ expr_l->getCast().getSize()
+ ));
+ expr_l->addGenCode(*expr_r);
+ expr_l->setCast(expr_r->getCast());
+ $$ = expr_l;
}
;
@@ -896,57 +1025,97 @@ node_assignment_expression:
| M4_ASSIGN_OP(`*=', `TOK_ASSIGN_MUL', `MUL', `int float')
| M4_ASSIGN_OP(`/=', `TOK_ASSIGN_DIV', `DIV', `int float')
| M4_ASSIGN_OP(`%=', `TOK_ASSIGN_MOD', `MOD', `int')
- | node_assignment_expression '?' node_jump_if0 node_assignment_expression node_jump ':' node_taddr node_assignment_expression
+ | node_assignment_expression '?' node_assignment_expression ':' node_assignment_expression
{
- Cast const& cast_cond = boost::any_cast<Cast const&>($1);
+ ExpressionInfoP expr_cond = boost::any_cast<ExpressionInfoP>($1);
+ Cast const& cast_cond = expr_cond->getCast();
+
if (cast_cond != Cast::ERROR && cast_cond != Cast::INT) {
yyerror("`int' cast expected before `?'");
- $$ = Cast::ERROR;
+ $$ = ExpressionInfoP(new ExpressionInfo());
+ break;
}
- Cast const& cast_l = boost::any_cast<Cast const&>($4);
- Cast const& cast_r = boost::any_cast<Cast const&>($8);
- if (cast_l != Cast::ERROR && cast_r != Cast::ERROR && cast_l != cast_r) {
+ ExpressionInfoP expr1 = boost::any_cast<ExpressionInfoP>($3);
+ ExpressionInfoP expr2 = boost::any_cast<ExpressionInfoP>($5);
+ Cast cast1 = expr1->getCast();
+ Cast cast2 = expr2->getCast();
+ if (cast1 != Cast::ERROR && cast2 != Cast::ERROR && cast1 != cast2) {
yyerror("cast mismatch");
- $$ = Cast::ERROR;
+ $$ = ExpressionInfoP(new ExpressionInfo());
+ break;
}
- p_comp->backpatchJUMP_IF0(boost::any_cast<vm_taddr_t>($3), boost::any_cast<vm_taddr_t>($7));
- p_comp->backpatchJUMP(boost::any_cast<vm_taddr_t>($5), p_comp->getCodeSize());
+ expr_cond->genCode(p_comp);
+ vm_taddr_t taddr1 = p_comp->genCodeJUMP_IF0();
+ expr1->genCode(p_comp);
+ vm_taddr_t taddr2 = p_comp->genCodeJUMP();
+ p_comp->backpatchJUMP_IF0(taddr1, p_comp->getCodeSize());
+ expr2->genCode(p_comp);
+ p_comp->backpatchJUMP(taddr2, p_comp->getCodeSize());
+
+ $$ = expr1;
}
- | node_assignment_expression TOK_OR node_jump_if0 node_true node_jump node_taddr node_assignment_expression
+ | node_assignment_expression TOK_OR node_assignment_expression
+ /*
+ * [e1]
+ * jump_if0 eval_e2
+ * push(1)
+ * jump exit
+ * eval_e2:
+ * [e2]
+ * exit:
+ */
{
- Cast const& cast1 = boost::any_cast<Cast const&>($1);
- Cast const& cast2 = boost::any_cast<Cast const&>($7);
+ ExpressionInfoP expr1 = boost::any_cast<ExpressionInfoP>($1);
+ ExpressionInfoP expr2 = boost::any_cast<ExpressionInfoP>($3);
+ Cast cast1 = expr1->getCast();
+ Cast cast2 = expr2->getCast();
if ((cast1 != Cast::ERROR && cast1 != Cast::INT) ||
(cast2 != Cast::ERROR && cast2 != Cast::INT))
{
yyerror(std::string("operation `||' not defined [") + cast1.getStr() + "]");
- $$ = Cast::ERROR;
+ ExpressionInfoP expr_result(new ExpressionInfo());
+ expr_result->setCast(Cast::INT);
+ $$ = expr_result;
break;
}
- p_comp->backpatchJUMP_IF0(boost::any_cast<vm_taddr_t>($3), boost::any_cast<vm_taddr_t>($6));
- p_comp->backpatchJUMP(boost::any_cast<vm_taddr_t>($5), p_comp->getCodeSize());
- $$ = $1;
+ expr1->genCode(p_comp);
+ vm_taddr_t taddr1 = p_comp->genCodeJUMP_IF0();
+ p_comp->genCodePUSH(1);
+ vm_taddr_t taddr2 = p_comp->genCodeJUMP();
+ p_comp->backpatchJUMP_IF0(taddr1, p_comp->getCodeSize());
+ expr2->genCode(p_comp);
+ p_comp->backpatchJUMP(taddr2, p_comp->getCodeSize());
+ $$ = expr1;
}
- | node_assignment_expression TOK_AND node_jump_if0 node_assignment_expression
+ | node_assignment_expression TOK_AND node_assignment_expression
{
- Cast const& cast1 = boost::any_cast<Cast const&>($1);
- Cast const& cast2 = boost::any_cast<Cast const&>($4);
+ ExpressionInfoP expr1 = boost::any_cast<ExpressionInfoP>($1);
+ ExpressionInfoP expr2 = boost::any_cast<ExpressionInfoP>($3);
+ Cast const& cast1 = expr1->getCast();
+ Cast const& cast2 = expr2->getCast();
+
if ((cast1 != Cast::ERROR && cast1 != Cast::INT) ||
(cast2 != Cast::ERROR && cast2 != Cast::INT))
{
yyerror(std::string("operation `&&' not defined [") + cast1.getStr() + "]");
- $$ = Cast::ERROR;
+ ExpressionInfoP expr_result(new ExpressionInfo());
+ expr_result->setCast(Cast::INT);
+ $$ = expr_result;
break;
}
- vm_taddr_t taddr = p_comp->genCodeJUMP();
- p_comp->backpatchJUMP_IF0(boost::any_cast<vm_taddr_t>($3), p_comp->getCodeSize());
+ expr1->genCode(p_comp);
+ vm_taddr_t taddr1 = p_comp->genCodeJUMP_IF0();
+ expr2->genCode(p_comp);
+ vm_taddr_t taddr2 = p_comp->genCodeJUMP();
+ p_comp->backpatchJUMP_IF0(taddr1, p_comp->getCodeSize());
p_comp->genCodePUSH(0);
- p_comp->backpatchJUMP(taddr, p_comp->getCodeSize());
- $$ = $1;
+ p_comp->backpatchJUMP(taddr2, p_comp->getCodeSize());
+
+ $$ = expr1;
}
| M4_BINARY_OP(`|', '|', `OR', `int')
| M4_BINARY_OP(`&', '&', `AND', `int')
@@ -969,22 +1138,25 @@ node_assignment_expression:
| M4_UNARY_OP(`-', '-', `NEG', `int float')
| '(' TOK_CAST ')' node_assignment_expression %prec UNARY_OP
{
- Cast const& cast_s = boost::any_cast<Cast const&>($4);
+ ExpressionInfoP expr = boost::any_cast<ExpressionInfoP>($4);
+ Cast const& cast_s = expr->getCast();
Cast const& cast_d = boost::any_cast<Cast const&>($2);
if (cast_s.getBase() == cast_d.getBase() || cast_s == Cast::ERROR)
;
- else if (cast_s.getBase() == Cast::INT && cast_d.getBase() == Cast::FLOAT)
- p_comp->genOprFLOAT_I();
- else if (cast_s.getBase() == Cast::FLOAT && cast_d.getBase() == Cast::INT)
- p_comp->genOprINT_F();
+ else if (cast_s.getBase() == Cast::INT && cast_d.getBase() == Cast::FLOAT) {
+ expr->addGenCode(bl::bind(&Comp::genOprFLOAT_I, bl::_1));
+ } else if (cast_s.getBase() == Cast::FLOAT && cast_d.getBase() == Cast::INT)
+ expr->addGenCode(bl::bind(&Comp::genOprINT_F, bl::_1));
else
yyerror(std::string("cannot convert cast[" + cast_s.getStr() + " -> " + cast_d.getStr() + "]"));
- $$ = $2;
+ expr->setCast(cast_d);
+ $$ = expr;
}
;
node_primary_expression:
TOK_ID {
+
std::string const& id = boost::any_cast<std::string const&>($1);
SymbolFunctionBase const* sym = p_comp->findFunctionBase(id);
if (sym == NULL) {
@@ -993,15 +1165,21 @@ node_primary_expression:
}
Cast const& cast = sym->getCast();
vm_dsize_t size = cast.getSize();
- if (size != 0)
- p_comp->genCodeEXPAND(size); // 戻り値
+ if (size == 0) {
+ $$ = ExpressionInfoP(new ExpressionInfo());
+ } else {
+ ExpressionInfoP expr_info(new ExpressionInfo(cast));
+ p_comp->genCodeEXPAND(size);
+ $$ = expr_info;
+ }
} '(' node_argument_list ')' {
std::string const& id = boost::any_cast<std::string const&>($1);
+ ExpressionInfoP expr_info = boost::any_cast<ExpressionInfoP>($2);
+ assert(expr_info);
CastListP const& cast_list(boost::any_cast<CastListP const&>($4));
SymbolFunctionBase const* sym = p_comp->findFunctionBase(id);
assert(sym != NULL);
-
int narg;
if (cast_list->size() != sym->getParamCount()) {
std::string msg((
@@ -1012,26 +1190,36 @@ node_primary_expression:
} else if (_doesExistMismatchedArg(&narg, *sym, *cast_list)) {
std::string msg((boost::format("argument #%d cast mismatch [%s]") % narg % id).str());
yyerror(msg);
- $$ = Cast::ERROR;
+ $$ = ExpressionInfoP(new ExpressionInfo());
break;
}
SymbolFunction const* sym_u = p_comp->findFunction(id);
if (sym_u != NULL) {
- vm_taddr_t taddr = p_comp->genCodeCALL(0);
- p_comp->pushFunctionCallAddr(id, taddr);
- $$ = sym_u->getCast();
+ expr_info->addGenCode(bl::bind(&Comp::genCodeCALL, bl::_1, 0));
+ expr_info->addGenCode(bl::bind(
+ &Comp::pushFunctionCallAddr,
+ bl::_1,
+ id,
+ bl::bind(&Comp::getCodeSize, bl::_1) - 1 // 1 for CALL
+ ));
+ $$ = expr_info;
break;
}
SymbolSyscall const* sym_s = p_comp->findSyscall(id);
if (sym_s != NULL) {
- p_comp->genCodeSYSCALL(sym_s->getSysNo(), sym_s->getParamSize());
- $$ = sym_s->getCast();
+ expr_info->addGenCode(boost::lambda::bind(
+ &Comp::genCodeSYSCALL,
+ bl::_1,
+ sym_s->getSysNo(),
+ sym_s->getParamSize()
+ ));
+ $$ = expr_info;
break;
}
- $$ = Cast::ERROR;
+ $$ = ExpressionInfoP(new ExpressionInfo());
}
| TOK_ID {
std::string const& id = boost::any_cast<std::string const&>($1);
@@ -1043,17 +1231,21 @@ node_primary_expression:
if ((sym_f = p_comp->findFunction(id)) != NULL) {
if (!sym_f->getCast().canUse(D_ARG)) {
yyerror(std::string("cannot use as arguments [" + id + "]"));
- $$ = Cast::ERROR;
+ $$ = ExpressionInfoP(new ExpressionInfo());
} else {
- _genPUSH(p_comp, sym_f->getAddr());
- $$ = sym_f->getCast();
+ ExpressionInfoP expr_info(new ExpressionInfo(sym_f->getCast()));
+ expr_info->addGenCode(bl::bind(&_genPushD, bl::_1, sym_f->getAddr()));
+ $$ = expr_info;
}
} else if (_getCodeGenEntry(&e, &sym, p_comp, id)) {
- (p_comp->*(e->gen_load))(sym->getAddr());
- $$ = sym->getCast();
+ ExpressionInfoP expr_info(new ExpressionInfo(sym->getCast()));
+ expr_info->addGenCode(
+ bl::bind(e->gen_load, bl::_1, sym->getAddr())
+ );
+ $$ = expr_info;
} else {
yyerror(std::string("undefined variable [" + id + "]"));
- $$ = Cast::ERROR;
+ $$ = ExpressionInfoP(new ExpressionInfo());
}
}
| TOK_ID TOK_INCREMENT { M4_PRE_POST_OP(1, `gen_load', `gen_inc') }
@@ -1061,18 +1253,23 @@ node_primary_expression:
| TOK_INCREMENT TOK_ID { M4_PRE_POST_OP(2, `gen_inc', `gen_load') }
| TOK_DECREMENT TOK_ID { M4_PRE_POST_OP(2, `gen_dec', `gen_load') }
| TOK_FLOAT {
- _genPUSH(p_comp, boost::any_cast<float>($1));
- $$ = Cast::FLOAT;
+ vm_float_t val = boost::any_cast<vm_float_t>($1);
+ ExpressionInfoP expr(new ExpressionInfo(val));
+ expr->addGenCode(bl::bind(&_genPushF, bl::_1, val));
+ $$ = expr;
}
| TOK_INT {
- _genPUSH(p_comp, boost::any_cast<vm_int_t>($1));
- $$ = Cast::INT;
+ vm_int_t val = boost::any_cast<vm_int_t>($1);
+ ExpressionInfoP expr(new ExpressionInfo(val));
+ expr->addGenCode(bl::bind(&_genPushI, bl::_1, val));
+ $$ = expr;
}
| node_literal {
Literal const* literal = p_comp->defineLiteral(boost::any_cast<std::string const&>($1));
assert(literal != NULL);
- p_comp->genCodePUSH(literal->getLiteralNo());
- $$ = Cast::STRING;
+ ExpressionInfoP expr(new ExpressionInfo(literal->getLiteralNo(), Cast::STRING));
+ expr->addGenCode(bl::bind(&Comp::genCodePUSH, bl::_1, literal->getLiteralNo()));
+ $$ = expr;
}
| '(' node_expression ')' {
$$ = $2;
@@ -1095,13 +1292,17 @@ node_argument_list0:
node_assignment_expression
{
CastListP cast_list(new CastList);
- cast_list->push_back(boost::any_cast<Cast const&>($1));
+ ExpressionInfoP expr = boost::any_cast<ExpressionInfoP>($1);
+ expr->genCode(p_comp);
+ cast_list->push_back(expr->getCast());
$$ = cast_list;
}
| node_argument_list0 ',' node_assignment_expression
{
CastListP& cast_list = boost::any_cast<CastListP&>($1);
- cast_list->push_back(boost::any_cast<Cast const&>($3));
+ ExpressionInfoP expr = boost::any_cast<ExpressionInfoP>($3);
+ expr->genCode(p_comp);
+ cast_list->push_back(expr->getCast());
$$ = $1;
}
;
--- a/tool/src/cscript/code/stdafx.h Fri Aug 10 08:33:42 2007 +0900
+++ b/tool/src/cscript/code/stdafx.h Fri Aug 17 00:07:02 2007 +0900
@@ -58,6 +58,7 @@
#include <boost/any.hpp>
#include <boost/cstdint.hpp>
#include <boost/format.hpp>
+#include <boost/function.hpp>
#include <boost/lambda/bind.hpp>
#include <boost/lambda/lambda.hpp>
#include <boost/lexical_cast.hpp>
--- a/tool/src/cscript/m4/parser.m4 Fri Aug 10 08:33:42 2007 +0900
+++ b/tool/src/cscript/m4/parser.m4 Fri Aug 17 00:07:02 2007 +0900
@@ -34,10 +34,10 @@ dnl ------------------------------------
dnl -----------------------------------------------------------------
m4_define(`M4_ASSIGN_OP',`TOK_ID $2 node_assignment_expression
{
- $$ = Cast::ERROR;
+ $$ = ExpressionInfoP(new ExpressionInfo());
std::string const& id = boost::any_cast<std::string const&>(`$'1);
- Cast const& cast_expr = boost::any_cast<Cast const&>(`$'3);
+ ExpressionInfoP expr = boost::any_cast<ExpressionInfoP>(`$'3);
SymbolVariable const* sym = NULL;
CodeGenEntry const* e = NULL;
@@ -46,29 +46,30 @@ m4_define(`M4_ASSIGN_OP',`TOK_ID $2 node
break;
}
- if (cast_expr != Cast::ERROR && sym->getCast() != cast_expr) {
+ if (expr && expr->getCast() != Cast::ERROR && sym->getCast() != expr->getCast()) {
yyerror(std::string("cast mismatch [" + id + "]"));
break;
}
+
vm_doffset_t varaddr = sym->getAddr();
m4_ifelse(m4_index($3, `NOP'), `-1',`dnl
- (p_comp->*(e->gen_load))(varaddr);
+ expr->addGenCode(bl::bind(e->gen_load, bl::_1, varaddr));
if (0)
;
m4_ifelse(m4_index($4, `int'), `-1',,`dnl
- else if (cast_expr.getBase() == Cast::INT)
- p_comp->genOpr$3_I();
+ else if (expr && expr->getCast().getBase() == Cast::INT)
+ expr->addGenCode(bl::bind(&Comp::genOpr$3_I, bl::_1));
')
m4_ifelse(m4_index($4, `float'), `-1',,`dnl
- else if (cast_expr.getBase() == Cast::FLOAT)
- p_comp->genOpr$3_F();
+ else if (expr && expr->getCast().getBase() == Cast::FLOAT)
+ expr->addGenCode(bl::bind(&Comp::genOpr$3_F, bl::_1));
')
- else if (cast_expr != Cast::ERROR)
- yyerror(std::string("operation ``$1'' not defined [") + cast_expr.getStr() + "]");
+ else if (expr && expr->getCast() != Cast::ERROR)
+ yyerror(std::string("operation ``$1'' not defined [") + expr->getCast().getStr() + "]");
')
- (p_comp->*(e->gen_store))(varaddr);
- $$ = sym->getCast();
+ expr->addGenCode(bl::bind(e->gen_store, bl::_1, varaddr));
+ $$ = expr;
}')dnl
dnl -----------------------------------------------------------------
dnl 定数に単項演算子を適用し、その場で値を計算する
@@ -140,20 +141,21 @@ dnl ------------------------------------
dnl -----------------------------------------------------------------
m4_define(`M4_UNARY_OP',`$2 node_assignment_expression %prec UNARY_OP
{
- Cast const& cast = boost::any_cast<Cast const&>(`$'2);
+ ExpressionInfoP expr = boost::any_cast<ExpressionInfoP>(`$'2);
+ Cast const& cast = expr->getCast();
if (cast == Cast::ERROR)
;
m4_ifelse(m4_index($4, `int'), `-1',,`dnl
else if (cast.getBase() == Cast::INT)
- p_comp->genOpr$3_I();
+ expr->addGenCode(bl::bind(&Comp::genOpr$3_I, bl::_1));
')
m4_ifelse(m4_index($4, `float'), `-1',,`dnl
else if (cast.getBase() == Cast::FLOAT)
- p_comp->genOpr$3_F();
+ expr->addGenCode(bl::bind(&Comp::genOpr$3_F, bl::_1));
')
else
yyerror(std::string("operation unary ``$1'' not defined[" + cast.getStr() + "]"));
- $$ = `$'2;
+ $$ = expr;
}')dnl
dnl -----------------------------------------------------------------
dnl 前置・後置演算子に対するコード生成
@@ -163,27 +165,30 @@ dnl $2.. 生成するコード列
dnl $2.. 生成するコード列
dnl CodeGenEntryのフィールド名
dnl -----------------------------------------------------------------
-m4_define(`M4_GEN_CODE', `m4_ifelse($#, 1,, `((p_comp->*e->$1))(varaddr);
+m4_define(`M4_GEN_CODE', `m4_ifelse($#, 1,, `
+ expr->addGenCode(bl::bind(e->$1, bl::_1, varaddr));
M4_GEN_CODE(m4_shift($@))')')
-m4_define(`M4_PRE_POST_OP', `dnl
- $$ = Cast::ERROR;
-
+m4_define(`M4_PRE_POST_OP', `
std::string const& id = boost::any_cast<std::string const&>(`$'$1);
CodeGenEntry const* e = NULL;
SymbolVariable const* sym = NULL;
if (!_getCodeGenEntry(&e, &sym, p_comp, id)) {
yyerror(std::string("undefined variable [" + id + "]"));
+ $$ = ExpressionInfoP();
break;
}
if (sym->getCast().getBase() != Cast::INT) {
yyerror(std::string("int variable expected [" + id + "]"));
+ $$ = ExpressionInfoP();
break;
}
+ ExpressionInfoP expr(new ExpressionInfo(sym->getCast()));
vm_doffset_t varaddr = sym->getAddr();
M4_GEN_CODE(m4_shift($@), `')
- $$ = sym->getCast();')
+ $$ = expr;
+')
dnl -----------------------------------------------------------------
dnl 二項演算子に対応するコード生成
dnl
@@ -196,30 +201,33 @@ dnl ------------------------------------
dnl -----------------------------------------------------------------
m4_define(`M4_BINARY_OP',`node_assignment_expression $2 node_assignment_expression
{
- Cast const& cast1 = boost::any_cast<Cast const&>(`$'1);
- Cast const& cast2 = boost::any_cast<Cast const&>(`$'3);
-
- if (cast1 != Cast::ERROR && cast2 != Cast::ERROR && cast1 != cast2) {
- yyerror("cast mismatch");
- $$ = Cast::ERROR;
+ ExpressionInfoP expr1 = boost::any_cast<ExpressionInfoP>(`$'1);
+ ExpressionInfoP expr2 = boost::any_cast<ExpressionInfoP>(`$'3);
+ if (expr1->getCast() == Cast::ERROR || expr2->getCast() == Cast::ERROR) {
+ $$ = ExpressionInfoP();
break;
}
- if (cast1 == Cast::ERROR) {
- $$ = Cast::ERROR;
+ Cast const& cast1 = expr1->getCast();
+ Cast const& cast2 = expr2->getCast();
+ if (cast1 != cast2) {
+ yyerror("cast mismatch");
+ $$ = ExpressionInfoP();
break;
}
m4_ifelse(m4_index($4, `int'), `-1',,`dnl
+ ExpressionInfoP expr(new ExpressionInfo(m4_ifelse($#, 4, cast1, Cast::m4_translit($5, `a-z', `A-Z'))));
+ expr->addGenCode(*expr1);
+ expr->addGenCode(*expr2);
+ $$ = expr;
if (cast1.getBase() == Cast::INT) {
- p_comp->genOpr$3_I();
- $$ = m4_ifelse($#, 4, `$'1, Cast::m4_translit($5, `a-z', `A-Z'));
+ expr->addGenCode(bl::bind(&Comp::genOpr$3_I, bl::_1));
break;
}')
m4_ifelse(m4_index($4, `float'), `-1',,`dnl
if (cast1.getBase() == Cast::FLOAT) {
- p_comp->genOpr$3_F();
- $$ = m4_ifelse($#, 4, `$'1, Cast::m4_translit($5, `a-z', `A-Z'));
+ expr->addGenCode(bl::bind(&Comp::genOpr$3_F, bl::_1));
break;
}')
yyerror(std::string("operation ``$1'' not defined [") + cast1.getStr() + "]");
- $$ = Cast::ERROR;
+ $$ = ExpressionInfoP();
}')dnl
--- a/tool/src/cscript/mk/codemak.mak Fri Aug 10 08:33:42 2007 +0900
+++ b/tool/src/cscript/mk/codemak.mak Fri Aug 17 00:07:02 2007 +0900
@@ -22,7 +22,7 @@ CPPFLAGS= $(CPPDEFS) -nostdinc -undef -
PROGS= cscrc$(EXE) cscvm$(EXE) cscds$(EXE) sysdecl$(EXE)
SRCS_COMMON= instrument.cc version.cc
-SRCS_CSCLIB= adler32.cc cast.cc inst.cc load.cc symbol.cc vm_loader.cc lex.yy.cc lex_re.cc
+SRCS_CSCLIB= adler32.cc cast.cc cscript_parser.cc inst.cc load.cc symbol.cc vm_loader.cc lex.yy.cc lex_re.cc
SRCS_CSCDS= cscds_main.cc
SRCS_CSCRC= parser.cc code.cc comp.cc dump.cc literal.cc cscrc_main.cc
SRCS_CSCVM= vm.cc vm_stdfunc.cc vm_sys_base.cc vm_sys_d.cc vm_sys_ud.cc cscvm_main.cc scr_stdfunc.cc test.sch.cc
--- a/tool/src/cscript/mk/cscript.mak Fri Aug 10 08:33:42 2007 +0900
+++ b/tool/src/cscript/mk/cscript.mak Fri Aug 17 00:07:02 2007 +0900
@@ -7,6 +7,7 @@ include $(TOP)/mk/common.mak
include $(TOP)/mk/common.mak
CSCRC= $(TOP)/$(TARGET).out/cscrc$(EXE)
+CSCDS= $(TOP)/$(TARGET).out/cscds$(EXE)
CSCRCFLAGS=
CPP= cpp
@@ -16,6 +17,7 @@ DEPS= $(addsuffix .scd,$(basename $(SRCS
DEPS= $(addsuffix .scd,$(basename $(SRCS)))
SCPS= $(addsuffix .scp,$(basename $(SRCS)))
SCBS= $(addsuffix .scb,$(basename $(SRCS)))
+DISS= $(addsuffix .dis,$(basename $(SRCS)))
%.scd: %.scs
$(echo-target)
@@ -29,10 +31,14 @@ SCBS= $(addsuffix .scb,$(basename $(SRCS
$(echo-target)
@$(CSCRC) $(CSCRCFLAGS) $<
-all: $(SCPS) $(SCBS)
+%.dis: %.scb $(CSCDS)
+ $(echo-target)
+ @$(CSCDS) $< > $@
+
+all: $(SCPS) $(SCBS) $(DISS)
clean:
- $(RM) $(SCPS) $(SCBS)
+ $(RM) $(SCPS) $(SCBS) $(DISS)
full: clean all
--- a/tool/src/cscript/mk/target/debug.mak Fri Aug 10 08:33:42 2007 +0900
+++ b/tool/src/cscript/mk/target/debug.mak Fri Aug 17 00:07:02 2007 +0900
@@ -1,4 +1,4 @@
# Makefile for cscript (debug target)
# $Id: debug.mak 452 2007-06-06 13:56:38Z issei $
-CXXOPTFLAGS= -g -O -felide-constructors -Wall -DBUILD='"debug"'
+CXXOPTFLAGS= -g -felide-constructors -Wall -Wextra -Wformat=2 -Wstrict-aliasing=2 -Wcast-qual -Wcast-align-Wwrite-strings -Wconversion -Wfloat-equal -Wpointer-arith -Wswitch-enum -DBUILD='"debug"'
--- a/tool/src/cscript/sample/while.scs Fri Aug 10 08:33:42 2007 +0900
+++ b/tool/src/cscript/sample/while.scs Fri Aug 17 00:07:02 2007 +0900
@@ -15,6 +15,12 @@ void main()
sysPrintS(" ");
}
sysPrintLn();
+
+ do {
+ sysPrintI(--i);
+ sysPrintS(" ");
+ } while (i > 0);
+ sysPrintLn();
}
// vim: syntax=c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tool/src/cscript/code/cscript_parser.cc Fri Aug 17 00:07:02 2007 +0900
@@ -0,0 +1,88 @@
+/*
+ * CScript コンパイラ 構文解析関連
+ * $Id: cscript_parser.h 426 2007-06-01 16:07:05Z issei $
+ *
+ * Copyright (c) 2006, 2007
+ * Issei Suzuki <issei@issei.org> All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include "cscript_parser.h"
+#include "comp.h"
+
+CSCRIPT_NAMESPACE_BEGIN
+
+ExpressionInfo::ExpressionInfo()
+ : m_cast(Cast::ERROR)
+ , m_is_const(false)
+{}
+
+ExpressionInfo::ExpressionInfo(Cast const& c)
+ : m_cast(c)
+ , m_is_const(false)
+{}
+
+ExpressionInfo::ExpressionInfo(vm_int_t n, Cast const& c)
+ : m_cast(c)
+ , m_val(n)
+ , m_is_const(true)
+{}
+
+ExpressionInfo::ExpressionInfo(vm_float_t f, Cast const& c)
+ : m_cast(c)
+ , m_val(f)
+ , m_is_const(true)
+{}
+
+ExpressionInfo::ExpressionInfo(std::string const& s, Cast const& c)
+ : m_cast(c)
+ , m_val(s)
+ , m_is_const(true)
+{}
+
+void ExpressionInfo::addGenCode(GenCode const& gen)
+{
+ m_gen_code_list.push_back(gen);
+}
+
+void ExpressionInfo::addGenCode(ExpressionInfo const& other)
+{
+ std::copy(
+ other.m_gen_code_list.begin(),
+ other.m_gen_code_list.end(),
+ std::back_inserter(m_gen_code_list)
+ );
+}
+
+void ExpressionInfo::genCode(Comp* comp)
+{
+ namespace bl = boost::lambda;
+
+ std::for_each(
+ m_gen_code_list.begin(),
+ m_gen_code_list.end(),
+ bl::bind(bl::_1, comp)
+ );
+
+ GenCodeList().swap(m_gen_code_list);
+}
+
+CSCRIPT_NAMESPACE_END
+