the tcc interface
The tcc calculator example compiles expressions to C for immediate compilation and execution using lm.tcc, the language machine interface to Fabrice Bellard's tiny C compiler. The tiny C compiler is a small and very fast C compiler that can be used a library to compile code to memory for direct execution. The interface modules makes the tcc library available to programs in the D language.
the rules
First, the tcc calculator rules as written in LMN:
.calc() - anything <- line - ; eof <- line eof; '\n' <- line ;
'\n' <- eof - ;
say output <- eof - ;
- line var Z; <- eof - say "error: " $(format("line %s char %s", varLn(N), varCn(N))) nl output;
- expr :N '=' <- eof - compile "void calc(){ printf(\"" message " %g\\n\\n\", " N ");}" output;
'?' expr :N '=' <- eof - compile "void calc(){ printf(\"" whatabout :"that" :"eh?" :N ");}" output;
'!' expr :N '=' <- eof - compile "void calc(){ printf(\"" whatabout :"this" :"eh?" :N ");}" output;
'@' expr :N '=' <- eof - compile "void calc(){ printf(\"" whatabout :"that" :"ok?" :N ");}" output;
'#' expr :N '=' <- eof - compile "void calc(){ printf(\"" whatabout :"this" :"ok?" :N ");}" output;
compile var Code; code :X execute("calc", X); <- eof - ;
output <- code :Code ; eof <- code :Code eof; - (Code) <- code - ; message <- code - "tcc says the answer is" ; whatabout :A :B :N <- code - "tcc says the answer is %12g - what about " A "? " B "\\n\\n\", " N ;
- out <- output - ; nl <- output - '\n' ;
.calc(0B)
'(' expr :N ')' <- opnd :{ "(" N ")" } ;
.calc()
- number :N <- opnd :{ "(double)" N };
- opnd :A op <- expr - ;
- <- op expr :A;
.calc(10L)
'+' expr :B <- op opnd :{A "+" B};
'-' expr :B <- op opnd :{A "-" B};
.calc(12L)
'*' expr :B <- op opnd :{A "*" B};
'/' expr :B <- op opnd :{A "/" B};
.calc(18L)
'-' opnd :A <- opnd :{ "-" A };
.calc(20L)
' ' <- - ;
'0' % { repeat .[0-7] % } octal yes toOct :N <- number :N;
[0-9] % { repeat .[0-9] % } { option '.' % repeat [0-9] % } toNum :N <- number :N;
'0x' .[0-9a-zA-Z] % { repeat .[0-9a-zA-Z] % } { option '.' % repeat [0-9] % } toHex :N <- number :N;
'0b' .[01] % { repeat .[01] % } toBin :N <- number :N;
.calc() - <- octal yes; '.' <- octal no ; 'x' <- octal no ; 'b' <- octal no ;
the main program in D
Next, the main program as written in the D language using the tcc compiler module:
import std.stdio; import std.string;
import lm.lmd; import lm.licenseGnuGPLv2; import lm.tcc;
extern (C) mode lmdInit(inout stream s);
int main(char[][]args) {
application a = new application(args, &lmdInit);
int result = a.start();
return result;
}
extern (C) element execute(inout stream s, element name, element func){
name = name.toVal();
func = func.toVal();
writefln("execute: %s", func);
compiler t = new compiler();
tccCode!(void) f = new tccCode!(void)(t, name.toString(), func.toString());
f.doit();
t.finish();
return null;
}
trying it out
Compile the calculator rules to internal format and wrap them to create an executable program called lmnCalc.gdc:
[peri@a4 examples]$ make tccCalc.gdc lmn2d -o calc2tcc.d calc2tcc.lmn /opt/gdc/bin/gdc -o tccCalc.gdc -I/usr/include -finline-functions -O3 calc2tcc.d tccCalc.d -ldl /usr/lib/liblm /usr/lib/liblmtcc -Wl,-rpath,/usr/lib -llm -llmtcc -ltcc
Try the calculator program:
[peri@a4 examples]$ ./tccCalc.gdc
103+17*3.23-3=
execute: void calc(){ printf("tcc says the answer is %g\n\n", (double)103+(double)17*(double)3.23-(double)3);}
tcc says the answer is 154.91
?103-17*3.23-3=
execute: void calc(){ printf("tcc says the answer is %12g - what about that? eh?\n\n", (double)103-(double)17*(double)3.23-(double)3);}
tcc says the answer is 45.09 - what about that? eh?
!103+17*3.23-3=
execute: void calc(){ printf("tcc says the answer is %12g - what about this? eh?\n\n", (double)103+(double)17*(double)3.23-(double)3);}
tcc says the answer is 154.91 - what about this? eh?
#103-17*3.23-3=
execute: void calc(){ printf("tcc says the answer is %12g - what about this? ok?\n\n", (double)103-(double)17*(double)3.23-(double)3);}
tcc says the answer is 45.09 - what about this? ok?
@103+17*3.23-3=
execute: void calc(){ printf("tcc says the answer is %12g - what about that? ok?\n\n", (double)103+(double)17*(double)3.23-(double)3);}
tcc says the answer is 154.91 - what about that? ok?






