CScript 論理和・論理積のコード出力も遅延するようにした。
authorIssei Suzuki <issei@issei.org>
Fri Aug 17 13:45:36 2007 +0900 (16 months ago)
changeset 5419b3fd6b93979
parent 5401db2af0d72e1
child 5426e81b5158064
CScript 論理和・論理積のコード出力も遅延するようにした。
tool/src/cscript/code/cscript_parser.cc
tool/src/cscript/code/cscript_parser.h
tool/src/cscript/code/parser.y
--- a/tool/src/cscript/code/cscript_parser.cc Fri Aug 17 11:57:09 2007 +0900
+++ b/tool/src/cscript/code/cscript_parser.cc Fri Aug 17 13:45:36 2007 +0900
@@ -56,6 +56,11 @@ void ExpressionInfo::addGenCode(GenCode
m_gen_code_list.push_back(gen);
}
+void ExpressionInfo::swapGenCode(GenCodeList& other)
+{
+ other.swap(m_gen_code_list);
+}
+
void ExpressionInfo::addGenCode(ExpressionInfo const& other)
{
std::copy(
--- a/tool/src/cscript/code/cscript_parser.h Fri Aug 17 11:57:09 2007 +0900
+++ b/tool/src/cscript/code/cscript_parser.h Fri Aug 17 13:45:36 2007 +0900
@@ -139,6 +139,7 @@ public:
void genCode(Comp* comp);
void addGenCode(GenCode const& gen);
void addGenCode(ExpressionInfo const& other);
+ void swapGenCode(GenCodeList& other);
private:
Cast m_cast;
--- a/tool/src/cscript/code/parser.y Fri Aug 17 11:57:09 2007 +0900
+++ b/tool/src/cscript/code/parser.y Fri Aug 17 13:45:36 2007 +0900
@@ -90,6 +90,15 @@ static bool _genSYSCALL(Comp* comp, std:
return true;
}
+static void _genCode(Comp* comp, GenCodeList const& gen_code_list)
+{
+ std::for_each(
+ gen_code_list.begin(),
+ gen_code_list.end(),
+ bl::bind(bl::_1, comp)
+ );
+}
+
/**
* 関数プロトタイプと関数呼び出し時の実引数型チェック
*
@@ -113,6 +122,122 @@ static bool _doesExistMismatchedArg(int*
}
return false;
}
+
+ANON_NAMESPACE_BEGIN
+// 二項論理演算 (共通処理)
+struct GenCodeLogicalBase
+{
+protected:
+ GenCodeLogicalBase(ExpressionInfoP expr1, ExpressionInfoP expr2)
+ {
+ expr1->swapGenCode(m_gen1);
+ expr2->swapGenCode(m_gen2);
+ }
+
+ GenCodeList m_gen1;
+ GenCodeList m_gen2;
+};
+
+// 論理積
+struct GenCodeLogicalAnd
+ : public GenCodeLogicalBase
+{
+ GenCodeLogicalAnd(ExpressionInfoP expr1, ExpressionInfoP expr2)
+ : GenCodeLogicalBase(expr1, expr2)
+ {}
+
+ /*
+ [expr1]
+ jump_if0 L_false
+ [expr2]
+ jump L_exit
+ L_false:
+ push 0
+ L_exit:
+ */
+ void operator()(Comp* comp) const
+ {
+ _genCode(comp, m_gen1);
+ vm_taddr_t taddr1 = comp->genCodeJUMP_IF0();
+ _genCode(comp, m_gen2);
+ vm_taddr_t taddr2 = comp->genCodeJUMP();
+ // L_fasle
+ comp->backpatchJUMP_IF0(taddr1, comp->getCodeSize());
+ comp->genCodePUSH(0);
+ comp->backpatchJUMP(taddr2, comp->getCodeSize());
+ // L_exit
+ }
+};
+
+// 論理和
+struct GenCodeLogicalOr
+ : public GenCodeLogicalBase
+{
+ GenCodeLogicalOr(ExpressionInfoP expr1, ExpressionInfoP expr2)
+ : GenCodeLogicalBase(expr1, expr2)
+ {}
+
+ /*
+ [expr1]
+ jump_if0 L_expr2
+ push 1
+ jump L_exit
+ L_expr2:
+ [expr2]
+ L_exit:
+ */
+ void operator()(Comp* comp) const
+ {
+ _genCode(comp, m_gen1);
+ vm_taddr_t taddr1 = comp->genCodeJUMP_IF0();
+ comp->genCodePUSH(1);
+ vm_taddr_t taddr2 = comp->genCodeJUMP();
+ comp->backpatchJUMP_IF0(taddr1, comp->getCodeSize());
+ // L_expr2
+ _genCode(comp, m_gen2);
+ // L_exit
+ comp->backpatchJUMP(taddr2, comp->getCodeSize());
+ }
+};
+
+// 三項演算子
+struct GenCode3Op
+{
+ GenCode3Op(ExpressionInfoP expr_cond, ExpressionInfoP expr_true, ExpressionInfoP expr_false)
+ {
+ expr_cond->swapGenCode(m_gen_cond);
+ expr_true->swapGenCode(m_gen_true);
+ expr_false->swapGenCode(m_gen_false);
+ }
+
+ /*
+ [expr_cond]
+ jump_if0 L_false
+ [expr_true]
+ jump L_exit
+ L_false:
+ [expr_false]
+ L_exit:
+ */
+ void operator()(Comp* comp) const
+ {
+ _genCode(comp, m_gen_cond);
+ vm_taddr_t taddr1 = comp->genCodeJUMP_IF0();
+ _genCode(comp, m_gen_true);
+ vm_taddr_t taddr2 = comp->genCodeJUMP();
+ comp->backpatchJUMP_IF0(taddr1, comp->getCodeSize());
+ // L_false
+ _genCode(comp, m_gen_false);
+ // L_exit
+ comp->backpatchJUMP(taddr2, comp->getCodeSize());
+ }
+
+private:
+ GenCodeList m_gen_cond;
+ GenCodeList m_gen_true;
+ GenCodeList m_gen_false;
+};
+ANON_NAMESPACE_END
%}
@@ -984,7 +1109,7 @@ node_assignment_expression:
| M4_ASSIGN_OP(`%=', `TOK_ASSIGN_MOD', `MOD', `int')
| node_assignment_expression '?' node_assignment_expression ':' node_assignment_expression
/*
- [expr]
+ [expr_cond]
jump_if0 L_false
[expr_true]
jump L_exit
@@ -995,102 +1120,57 @@ node_assignment_expression:
{
ExpressionInfoP expr_cond = boost::any_cast<ExpressionInfoP>($1);
Cast const& cast_cond = expr_cond->getCast();
+ ExpressionInfoP expr_true = boost::any_cast<ExpressionInfoP>($3);
+ ExpressionInfoP expr_false = boost::any_cast<ExpressionInfoP>($5);
+ Cast const& cast_true = expr_true->getCast();
+ Cast const& cast_false = expr_false->getCast();
- if (cast_cond != Cast::ERROR && cast_cond != Cast::INT) {
+ ExpressionInfoP expr(new ExpressionInfo());
+
+ if (cast_cond != Cast::ERROR && cast_cond != Cast::INT)
yyerror("`int' cast expected before `?'");
- $$ = ExpressionInfoP(new ExpressionInfo());
- break;
+ else if (cast_true != Cast::ERROR && cast_false != Cast::ERROR && cast_true != cast_false)
+ yyerror("cast mismatch");
+ else {
+ expr->setCast(cast_true);
+ expr->addGenCode(GenCode3Op(expr_cond, expr_true, expr_false));
}
- ExpressionInfoP expr1 = boost::any_cast<ExpressionInfoP>($3);
- ExpressionInfoP expr2 = boost::any_cast<ExpressionInfoP>($5);
- Cast const& cast1 = expr1->getCast();
- Cast const& cast2 = expr2->getCast();
- if (cast1 != Cast::ERROR && cast2 != Cast::ERROR && cast1 != cast2) {
- yyerror("cast mismatch");
- $$ = ExpressionInfoP(new ExpressionInfo());
- break;
- }
-
- 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;
+ $$ = expr;
}
| node_assignment_expression TOK_OR node_assignment_expression
- /*
- [expr1]
- jump_if0 L_expr2
- push 1
- jump L_exit
- L_expr2:
- [expr2]
- L_exit:
- */
- {
- 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() + "]");
- ExpressionInfoP expr_result(new ExpressionInfo());
- expr_result->setCast(Cast::INT);
- $$ = expr_result;
- break;
- }
-
- 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_assignment_expression
- /*
- [expr1]
- jump_if0 L_false
- [expr2]
- jump L_exit
- L_false:
- push 0
- L_exit:
- */
{
ExpressionInfoP expr1 = boost::any_cast<ExpressionInfoP>($1);
ExpressionInfoP expr2 = boost::any_cast<ExpressionInfoP>($3);
Cast const& cast1 = expr1->getCast();
Cast const& cast2 = expr2->getCast();
+ ExpressionInfoP expr(new ExpressionInfo());
+ expr->setCast(Cast::INT);
+
if ((cast1 != Cast::ERROR && cast1 != Cast::INT) ||
(cast2 != Cast::ERROR && cast2 != Cast::INT))
- {
+ yyerror(std::string("operation `||' not defined [") + cast1.getStr() + "]");
+ else
+ expr->addGenCode(GenCodeLogicalOr(expr1, expr2));
+ $$ = expr;
+ }
+ | node_assignment_expression TOK_AND node_assignment_expression
+ {
+ ExpressionInfoP expr1 = boost::any_cast<ExpressionInfoP>($1);
+ ExpressionInfoP expr2 = boost::any_cast<ExpressionInfoP>($3);
+ Cast const& cast1 = expr1->getCast();
+ Cast const& cast2 = expr2->getCast();
+
+ ExpressionInfoP expr(new ExpressionInfo());
+ expr->setCast(Cast::INT);
+
+ if ((cast1 != Cast::ERROR && cast1 != Cast::INT) ||
+ (cast2 != Cast::ERROR && cast2 != Cast::INT))
yyerror(std::string("operation `&&' not defined [") + cast1.getStr() + "]");
- ExpressionInfoP expr_result(new ExpressionInfo());
- expr_result->setCast(Cast::INT);
- $$ = expr_result;
- break;
- }
-
- 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(taddr2, p_comp->getCodeSize());
-
- $$ = expr1;
+ else
+ expr->addGenCode(GenCodeLogicalAnd(expr1, expr2));
+ $$ = expr;
}
| M4_BINARY_OP(`|', '|', `OR', `int')
| M4_BINARY_OP(`&', '&', `AND', `int')