// $Source$
// $Revision$
// $Date$
$use Apply Box Class Convert StdIO Table;
$use "rfpc";
$use "rfp_helper";
$box Func-Names;
$table Func-Table;
$box Var-Names;
$table Var-Table;
$func ASAIL-To-CPP e.body = e.cpp-code;
// Constructs legal C++ name from e.Name and stores it in the appropriate box
// and table
$func Name-To-CPP t.Name = e.legal-cpp-name;
$func Build-CPP-Name e.words = e.cpp-chars;
$func Find-Unused-Name (e.used-names) e.name = e.unused-name;
$func Word-To-CPP-Chars s.word = e.cpp-chars;
$func Chars-To-CPP-Chars e.chars = e.cpp-chars;
$func Expr-To-CPP (e.ASAIL-Expr-init ) e.ASAIL-Expr-rest = e.ASAIL-Expr;
$func Expr-Ref-To-CPP s.inner-call? e.ASAIL-Expr-Ref = e.CPP-Expr-Ref;
$func Expr-Int-To-CPP e.ASAIL-Expr-Int = e.CPP-Expr-Int;
$func Step-To-CPP e.step-operators = e.cpp-step-operators;
$func Const-Expr-To-CPP e.ASAIL-const-expr = e.CPP-const-expr;
$func Args-To-CPP (e.Arg-Res-Tag) e.ASAIL-Args = e.CPP-Args;
$func Symbol-To-CPP s.RFP-Symbol = e.CPP-String;
$func Chars-To-CPP e.expr = e.CPP-String;
$func Cond-To-CPP e.cond = e.CPP-Cond;
$func Infix-To-CPP s.func-for-converting-args-to-cpp s.op e.args = e.cpp-expr;
$func Op-Arg-To-CPP s.op = s.func-for-converting-args-to-cpp;
RFP-ASAIL-To-CPP e.asail =
,
,
;
ASAIL-To-CPP e.asail, {
e.asail : t.item e.rest, t.item : {
(FUNC t.name (e.args) (e.ress) e.body) =
,
,
('RF_FUNC (' ', '
'(' '), '
'(' '))'
()
'RF_END');
(IF (e.cond) e.body) =
('if (' ')')
('{' () '}');
(FOR (e.label) (e.cond) (e.step) e.body) =
{
e.label : t = (LABEL ': {}');;
} :: e.label,
('for ( ; ' '; ' ')')
('{' () e.label '}');
(LABEL t.label e.body) =
('{' () '}')
(LABEL ': {}');
(TRY e.body) =
('try {' () '}');
(CATCH-ERROR e.body) =
('with {' () '}');
RETURN = ('return true;');
RETFAIL = ('retfail;');
FATAL = ('error ("Unexpected fail");');
(LSPLIT e.expr (e.min) t.var1 t.var2) =
('lsplit (' ', ' ', '
', ' ');');
(RSPLIT e.expr (e.min) t.var1 t.var2) =
('rsplit (' ', ' ', '
', ' ');');
(ASSIGN t.var e.expr) =
( ' = ' ';');
(DECL s.type t.var) =
(s.type ' ' ';');
(EXPR t.var e.expr) =
('Expr ' ' (' ');');
(DEREF t.var e.expr (e.pos)) =
('Expr ' ' (' ', '
');');
(SUBEXPR t.var e.expr (e.pos) (e.len)) =
('Expr ' ' ('
', ' ', '
');');
(DROP t.var) =
( '.drop ();');
(CONTINUE t.label) =
('goto ' ';');
(BREAK t.label) =
('goto ' ';');
(ERROR e.expr) =
('error (' ');');
(CONSTEXPR t.name e.expr) =
('const Expr ' ' = ' ';');
(DECL-FUNC t.name) =
('RF_DECL (' ');');
/*
* s.call can be CALL or TAILCALL
*/
(s.call t.name (e.exprs) (e.ress)) =
('RF_' s.call ' (' ', '
'(' '), (' '));');
} :: e.cpp-item,
e.cpp-item ;
/*empty*/;
};
/*
* Determine type of e.expr - int or Refal.
*/
Expr-To-CPP (e.init) e.expr-all, e.expr-all : {
/*empty*/ = ;
(VAR (e.QualifiedName)) e.rest =
;
s.ObjectSymbol e.rest, {
= ;
;
};
(PAREN e.expr) e.rest = ;
(EXPR e.expr) e.rest = ;
(DEREF e.expr) e.rest = ;
(SUBEXPR e.expr) e.rest = ;
(LENGTH e.expr) e.rest = ;
(MAX e.args) e.rest = ;
(MIN e.args) e.rest = ;
(INFIX s.op e.args) e.rest = ;
};
Expr-Ref-To-CPP s.inner-call? e.expr-ref, e.expr-ref : {
t.item e.rest =
{
e.rest : v = ' + ';
/*empty*/;
} :: e.plus,
t.item : {
s.ObjectSymbol = ;
(PAREN e.expr) = ' ()';
(EXPR e.expr) =
'Expr (' ')';
(DEREF e.expr (e.pos)) =
'Expr (' ', '
')';
(SUBEXPR e.expr (e.pos) (e.len)) =
'Expr (' ', '
', ' ')';
(VAR (e.QualifiedName)) = ;
ex = $error ("Illegal type ref-expr : " ex );
} :: e.cpp-item,
e.cpp-item e.plus ;
/*empty*/ =
{
s.inner-call? : 1 = /*empty*/;
'empty';
};
};
Expr-Int-To-CPP {
t.item e.rest =
{
e.rest : v = ' + ';
/*empty*/;
} :: e.plus,
t.item : {
s.ObjectSymbol =
{
= ;
$error ("Illegal type int-symbol: " s.ObjectSymbol);
};
(LENGTH e.expr) =
'(int) ' '.get_len ()';
(MAX e.args) =
'max (' ')';
(MIN e.args) =
'min (' ')';
(INFIX s.op e.args) =
'(' ')';
(VAR (e.QualifiedName)) = ;
ex = $error ("Illegal type ref-int : " ex );
} :: e.cpp-item,
e.cpp-item e.plus ;
/*empty*/ = /*empty*/;
};
Cond-To-CPP {
/*empty*/ = /*empty*/;
t.cond-term e.rest =
{
e.rest : v = ' && ';
/*empty*/;
} :: e.and,
t.cond-term : {
(CALL t.name (e.exprs) (e.ress)) =
'RF_CALL (' ', '
'(' '), '
'(' '))';
(SYMBOL? e.expr (e.pos)) =
'.symbol_at (' ')';
(FLAT-SUBEXPR? e.expr (e.pos) (e.len)) =
'.flat_at ('
', ' ')';
/*
* EQ -> to function eq() with 6 arg.
*/
(EQ (e.expr1) (e.pos1) (e.len1) (e.expr2) (e.pos2) (e.len2)) =
'eq (' ', '
', ' ', '
', '
', ' ')';
/*
* FLAT-EQ -> to function flat_eq() with 5 arg.
*/
(FLAT-EQ (e.expr1) (e.pos1) (e.expr2) (e.pos2) (e.len)) =
'flat_eq (' ', ' ', '
', ' ', '
')';
(NOT e.cond) =
'!' ;
(INFIX s.op e.args) =
'(' s.op e.args> ')';
} :: e.cpp-term,
e.cpp-term e.and ;
};
Infix-To-CPP s.arg2cpp s.op e.args, {
e.args : (e.arg) e.rest =
{
e.rest : v = ' ' s.op ' ';
/*empty*/;
} :: e.cpp-op,
e.cpp-op ;;
};
Op-Arg-To-CPP s.op, {
s.op : \{ "&&"; "||"; } = &Cond-To-CPP;
s.op : \{ "<"; ">"; "<="; ">="; "=="; "+"; "-"; "%"; "*"; "/"; } = &Expr-Int-To-CPP;
};
Step-To-CPP {
/*empty*/ = /*empty*/;
(INC-ITER t.var) = 'iter(' ')++';
};
Const-Expr-To-CPP {
/*empty*/ = 'empty';
e.expr =
{
e.expr : (e) e = /*empty*/;
'(Expr) ';
} :: e.cpp-expr,
e.expr (e.cpp-expr) $iter {
e.expr : t.item e.rest,
{
e.rest : v = ' + ';
/*empty*/;
} :: e.plus,
t.item : \{
(PAREN e.paren-expr) =
'(' ') ()';
(REF (e.QualifiedName s.name)) =
;
} :: e.cpp-item =
e.rest (e.cpp-expr e.cpp-item e.plus);
e.expr : e.chars (e1) e2 =
(e1) e2 (e.cpp-expr ' + ');
/*empty*/ (e.cpp-expr );
} :: e.expr (e.cpp-expr),
e.expr : /*empty*/ =
e.cpp-expr;
};
/*
* Gets function name or variable and returns legal C++ name corresponding to
* it. If is called with such parameter at the first time then stores C++ name
* in the appropriate table for further using. Also put new name in the
* appropriate box. Box and table for variables is updated for each new
* function and box and table for functions is updated for each new module.
*/
Name-To-CPP term =
term : {
(VAR (e.QualifiedName)) = e.QualifiedName &Var-Names &Var-Table;
(LABEL (e.QualifiedName)) = e.QualifiedName &Var-Names &Var-Table;
(e.QualifiedName) = e.QualifiedName &Func-Names &Func-Table; // function name
} :: e.QualifiedName s.used-names s.table,
{
;
e.QualifiedName : s.first e.last,
:: e.first,
{
e.first : s.char e,
, # \{ s.char : '?'; } =
(e.first) e.last;
('R_' e.first) e.last;
} :: (e.first) e.last,
e.first :: e.name,
) e.name> :: e.name,
,
,
e.name;
};
Build-CPP-Name {
s.word e.rest = '_' ;
/*empty*/ = /*empty*/;
};
Find-Unused-Name (e.used-names) e.name, {
e.used-names : e1 (e.name) e2 = ;
e.name;
};
Word-To-CPP-Chars {
"+" = '__add__';
"-" = '__sub__';
"*" = '__mult__';
s.word = >;
};
Chars-To-CPP-Chars {
s.sym e.chars, {
s.sym : '?' = '_';
\{ ; ; } = s.sym;
'_';
} :: s.sym =
s.sym ;
/*empty*/ = /*empty*/;
};
Args-To-CPP {
(e.prefix) Vars /*empty*/ = /*empty*/;
(e.prefix) s.tag e.args =
e.args () $iter {
e.args : (e.arg) e.rest =
{
e.rest : v = ', ';
/*empty*/;
} :: e.comma,
s.tag : {
Vars = e.rest (e.cpp-args e.comma);
Exprs = e.rest (e.cpp-args e.comma);
Ints = e.rest (e.cpp-args e.comma);
};
} :: e.args (e.cpp-args),
e.args : /*empty*/,
e.prefix e.cpp-args;
};
Symbol-To-CPP s.ObjectSymbol, {
= s.ObjectSymbol;
() $iter {
e.symbol : s.char e.rest, s.char : {
'\\' = '\\\\';
'\n' = '\\n';
'\t' = '\\t';
// '\v' = '\\v';
// '\b' = '\\b';
'\r' = '\\r';
// '\f' = '\\f';
'\"' = '\\"';
'\'' = '\\\'';
s = s.char;
} :: e.cpp-char,
e.rest (e.cpp-symbol e.cpp-char);
} :: e.symbol (e.cpp-symbol),
e.symbol : /*empty*/,
'\"' e.cpp-symbol '\"';
};
Chars-To-CPP e.expr = >;