compiler: Formatting
This commit is contained in:
+6
-6
@@ -4,12 +4,12 @@
|
||||
|
||||
#include "..\LinkerLib\linker.hpp"
|
||||
|
||||
class Assem{
|
||||
public:
|
||||
istream ∈
|
||||
Module *mod;
|
||||
Assem( istream &in,Module *mod ):in( in ),mod( mod ){}
|
||||
virtual void assemble()=0;
|
||||
class Assem {
|
||||
public:
|
||||
istream& in;
|
||||
Module* mod;
|
||||
Assem(istream& in, Module* mod) : in(in), mod(mod) {}
|
||||
virtual void assemble() = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
+2870
-577
File diff suppressed because it is too large
Load Diff
+298
-188
@@ -7,302 +7,412 @@
|
||||
|
||||
*/
|
||||
|
||||
#include "../std.h"
|
||||
#include "../ex.h"
|
||||
#include "assem_x86.h"
|
||||
#include "../ex.h"
|
||||
#include "../std.h"
|
||||
|
||||
#include <iomanip>
|
||||
|
||||
typedef map<string,Inst*> InstMap;
|
||||
typedef InstMap::value_type InstPair;
|
||||
typedef map<string, Inst*> InstMap;
|
||||
typedef InstMap::value_type InstPair;
|
||||
typedef InstMap::const_iterator InstIter;
|
||||
|
||||
static InstMap instMap;
|
||||
|
||||
//#define LOG
|
||||
|
||||
Assem_x86::Assem_x86( istream &in,Module *mod ):Assem(in,mod){
|
||||
|
||||
Assem_x86::Assem_x86(istream& in, Module* mod) : Assem(in, mod)
|
||||
{
|
||||
//build instruction map, if not built already.
|
||||
if( !instMap.size() ){
|
||||
for( int k=0;!insts[k].name || insts[k].name[0];++k ){
|
||||
if( insts[k].name ) instMap.insert( InstPair( insts[k].name,&insts[k] ) );
|
||||
if (!instMap.size()) {
|
||||
for (int k = 0; !insts[k].name || insts[k].name[0]; ++k) {
|
||||
if (insts[k].name)
|
||||
instMap.insert(InstPair(insts[k].name, &insts[k]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int findCC( const string &s ){
|
||||
if( s=="o" ) return 0;
|
||||
if( s=="no" ) return 1;
|
||||
if( s=="b"||s=="c"||s=="nae" ) return 2;
|
||||
if( s=="ae"||s=="nb"||s=="nc" ) return 3;
|
||||
if( s=="e"||s=="z" ) return 4;
|
||||
if( s=="ne"||s=="nz" ) return 5;
|
||||
if( s=="be"||s=="na" ) return 6;
|
||||
if( s=="a"||s=="nbe" ) return 7;
|
||||
if( s=="s" ) return 8;
|
||||
if( s=="ns" ) return 9;
|
||||
if( s=="p"||s=="pe" ) return 10;
|
||||
if( s=="ne"||s=="po" ) return 11;
|
||||
if( s=="l"||s=="nge" ) return 12;
|
||||
if( s=="ge"||s=="nl" ) return 13;
|
||||
if( s=="le"||s=="ng" ) return 14;
|
||||
if( s=="g"||s=="nle" ) return 15;
|
||||
static int findCC(const string& s)
|
||||
{
|
||||
if (s == "o")
|
||||
return 0;
|
||||
if (s == "no")
|
||||
return 1;
|
||||
if (s == "b" || s == "c" || s == "nae")
|
||||
return 2;
|
||||
if (s == "ae" || s == "nb" || s == "nc")
|
||||
return 3;
|
||||
if (s == "e" || s == "z")
|
||||
return 4;
|
||||
if (s == "ne" || s == "nz")
|
||||
return 5;
|
||||
if (s == "be" || s == "na")
|
||||
return 6;
|
||||
if (s == "a" || s == "nbe")
|
||||
return 7;
|
||||
if (s == "s")
|
||||
return 8;
|
||||
if (s == "ns")
|
||||
return 9;
|
||||
if (s == "p" || s == "pe")
|
||||
return 10;
|
||||
if (s == "ne" || s == "po")
|
||||
return 11;
|
||||
if (s == "l" || s == "nge")
|
||||
return 12;
|
||||
if (s == "ge" || s == "nl")
|
||||
return 13;
|
||||
if (s == "le" || s == "ng")
|
||||
return 14;
|
||||
if (s == "g" || s == "nle")
|
||||
return 15;
|
||||
return -1;
|
||||
}
|
||||
|
||||
void Assem_x86::align( int n ){
|
||||
int pc=mod->getPC();
|
||||
int sz=(pc+(n-1))/n*n-pc;
|
||||
while( sz-- ) mod->emit( 0x90 );
|
||||
void Assem_x86::align(int n)
|
||||
{
|
||||
int pc = mod->getPC();
|
||||
int sz = (pc + (n - 1)) / n * n - pc;
|
||||
while (sz--)
|
||||
mod->emit(0x90);
|
||||
}
|
||||
|
||||
void Assem_x86::emit( int n ){
|
||||
void Assem_x86::emit(int n)
|
||||
{
|
||||
#ifdef LOG
|
||||
clog<<hex<<(int(n)&0xff)<<dec<<' ';
|
||||
clog << hex << (int(n) & 0xff) << dec << ' ';
|
||||
#endif
|
||||
mod->emit( n );
|
||||
mod->emit(n);
|
||||
}
|
||||
|
||||
void Assem_x86::emitw( int n ){
|
||||
emit( n );
|
||||
emit( (n>>8) );
|
||||
void Assem_x86::emitw(int n)
|
||||
{
|
||||
emit(n);
|
||||
emit((n >> 8));
|
||||
}
|
||||
|
||||
void Assem_x86::emitd( int n ){
|
||||
emitw( n );
|
||||
emitw( n>>16 );
|
||||
void Assem_x86::emitd(int n)
|
||||
{
|
||||
emitw(n);
|
||||
emitw(n >> 16);
|
||||
}
|
||||
|
||||
void Assem_x86::emitImm( const Operand &o,int size ){
|
||||
void Assem_x86::emitImm(const Operand& o, int size)
|
||||
{
|
||||
if (size < 4 && o.immLabel.size())
|
||||
throw Ex("immediate value cannot by a label");
|
||||
|
||||
if( size<4 && o.immLabel.size() ) throw Ex( "immediate value cannot by a label" );
|
||||
|
||||
switch( size ){
|
||||
case 1:emit( o.imm );return;
|
||||
case 2:emitw( o.imm );return;
|
||||
case 4:a_reloc( o.immLabel );emitd( o.imm );return;
|
||||
switch (size) {
|
||||
case 1:
|
||||
emit(o.imm);
|
||||
return;
|
||||
case 2:
|
||||
emitw(o.imm);
|
||||
return;
|
||||
case 4:
|
||||
a_reloc(o.immLabel);
|
||||
emitd(o.imm);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void Assem_x86::emitImm( const string &s,int size ){
|
||||
|
||||
Operand op(s);op.parse();
|
||||
if( !(op.mode&IMM) ) throw Ex( "operand must be immediate" );
|
||||
emitImm( op,size );
|
||||
void Assem_x86::emitImm(const string& s, int size)
|
||||
{
|
||||
Operand op(s);
|
||||
op.parse();
|
||||
if (!(op.mode & IMM))
|
||||
throw Ex("operand must be immediate");
|
||||
emitImm(op, size);
|
||||
}
|
||||
|
||||
void Assem_x86::r_reloc( const string &s ){
|
||||
if( !s.size() ) return;
|
||||
mod->addReloc( s.c_str(),mod->getPC(),true );
|
||||
void Assem_x86::r_reloc(const string& s)
|
||||
{
|
||||
if (!s.size())
|
||||
return;
|
||||
mod->addReloc(s.c_str(), mod->getPC(), true);
|
||||
}
|
||||
|
||||
void Assem_x86::a_reloc( const string &s ){
|
||||
if( !s.size() ) return;
|
||||
mod->addReloc( s.c_str(),mod->getPC(),false );
|
||||
void Assem_x86::a_reloc(const string& s)
|
||||
{
|
||||
if (!s.size())
|
||||
return;
|
||||
mod->addReloc(s.c_str(), mod->getPC(), false);
|
||||
}
|
||||
|
||||
void Assem_x86::assemInst( const string &name,const string &lhs,const string &rhs ){
|
||||
|
||||
void Assem_x86::assemInst(const string& name, const string& lhs, const string& rhs)
|
||||
{
|
||||
//parse operands
|
||||
Operand lop( lhs ),rop( rhs );
|
||||
lop.parse();rop.parse();
|
||||
Operand lop(lhs), rop(rhs);
|
||||
lop.parse();
|
||||
rop.parse();
|
||||
|
||||
//find instruction
|
||||
int cc=-1;
|
||||
Inst *inst=0;
|
||||
int cc = -1;
|
||||
Inst* inst = 0;
|
||||
|
||||
//kludge for condition code instructions...
|
||||
if( name[0]=='j' ){
|
||||
if( (cc=findCC(name.substr(1)))>=0 ){
|
||||
static Inst jCC={ "jCC",IMM,NONE,RW_RD|PLUSCC,"\x2\x0F\x80" };
|
||||
inst=&jCC;
|
||||
if (name[0] == 'j') {
|
||||
if ((cc = findCC(name.substr(1))) >= 0) {
|
||||
static Inst jCC = {"jCC", IMM, NONE, RW_RD | PLUSCC, "\x2\x0F\x80"};
|
||||
inst = &jCC;
|
||||
}
|
||||
}else if( name[0]=='s' && name.substr( 0,3 )=="set" ){
|
||||
if( (cc=findCC(name.substr(3)))>=0 ){
|
||||
static Inst setCC={ "setne",R_M8,NONE,_2|PLUSCC,"\x2\x0F\x90" };
|
||||
inst=&setCC;
|
||||
} else if (name[0] == 's' && name.substr(0, 3) == "set") {
|
||||
if ((cc = findCC(name.substr(3))) >= 0) {
|
||||
static Inst setCC = {"setne", R_M8, NONE, _2 | PLUSCC, "\x2\x0F\x90"};
|
||||
inst = &setCC;
|
||||
}
|
||||
}
|
||||
|
||||
if( inst ){
|
||||
if( !(lop.mode&inst->lmode) || !(rop.mode&inst->rmode) ) throw Ex( "illegal addressing mode" );
|
||||
}else{
|
||||
InstIter it=instMap.find( name );
|
||||
if( it==instMap.end() ) throw Ex( "unrecognized instruction" );
|
||||
inst=it->second;
|
||||
for(;;){
|
||||
if( (lop.mode&inst->lmode) && (rop.mode&inst->rmode) ) break;
|
||||
if( (++inst)->name ) throw Ex( "illegal addressing mode" );
|
||||
if (inst) {
|
||||
if (!(lop.mode & inst->lmode) || !(rop.mode & inst->rmode))
|
||||
throw Ex("illegal addressing mode");
|
||||
} else {
|
||||
InstIter it = instMap.find(name);
|
||||
if (it == instMap.end())
|
||||
throw Ex("unrecognized instruction");
|
||||
inst = it->second;
|
||||
for (;;) {
|
||||
if ((lop.mode & inst->lmode) && (rop.mode & inst->rmode))
|
||||
break;
|
||||
if ((++inst)->name)
|
||||
throw Ex("illegal addressing mode");
|
||||
}
|
||||
}
|
||||
|
||||
//16/32 bit modifier - NOP for now
|
||||
if( inst->flags & (O16|O32) ){}
|
||||
if (inst->flags & (O16 | O32)) {
|
||||
}
|
||||
|
||||
int k,n=inst->bytes[0];
|
||||
for( k=1;k<n;++k ) emit( inst->bytes[k] );
|
||||
if( inst->flags&PLUSREG ) emit( inst->bytes[k]+lop.reg );
|
||||
else if( inst->flags&PLUSCC ) emit( inst->bytes[k]+cc );
|
||||
else emit( inst->bytes[k] );
|
||||
|
||||
if( inst->flags&(_0|_1|_2|_3|_4|_5|_6|_7|_R ) ){
|
||||
int k, n = inst->bytes[0];
|
||||
for (k = 1; k < n; ++k)
|
||||
emit(inst->bytes[k]);
|
||||
if (inst->flags & PLUSREG)
|
||||
emit(inst->bytes[k] + lop.reg);
|
||||
else if (inst->flags & PLUSCC)
|
||||
emit(inst->bytes[k] + cc);
|
||||
else
|
||||
emit(inst->bytes[k]);
|
||||
|
||||
if (inst->flags & (_0 | _1 | _2 | _3 | _4 | _5 | _6 | _7 | _R)) {
|
||||
//find the memop;
|
||||
const Operand &mop=
|
||||
(inst->rmode&(MEM|MEM8|MEM16|MEM32|R_M|R_M8|R_M16|R_M32))?rop:lop;
|
||||
const Operand& mop = (inst->rmode & (MEM | MEM8 | MEM16 | MEM32 | R_M | R_M8 | R_M16 | R_M32)) ? rop : lop;
|
||||
|
||||
//find the spare field value.
|
||||
int rm=0;
|
||||
switch( inst->flags&(_0|_1|_2|_3|_4|_5|_6|_7|_R ) ){
|
||||
case _0:rm=0;break;case _1:rm=1;break;case _2:rm=2;break;case _3:rm=3;break;
|
||||
case _4:rm=4;break;case _5:rm=5;break;case _6:rm=6;break;case _7:rm=7;break;
|
||||
case _R:rm=(inst->rmode&(REG8|REG16|REG32))?rop.reg:lop.reg;break;
|
||||
int rm = 0;
|
||||
switch (inst->flags & (_0 | _1 | _2 | _3 | _4 | _5 | _6 | _7 | _R)) {
|
||||
case _0:
|
||||
rm = 0;
|
||||
break;
|
||||
case _1:
|
||||
rm = 1;
|
||||
break;
|
||||
case _2:
|
||||
rm = 2;
|
||||
break;
|
||||
case _3:
|
||||
rm = 3;
|
||||
break;
|
||||
case _4:
|
||||
rm = 4;
|
||||
break;
|
||||
case _5:
|
||||
rm = 5;
|
||||
break;
|
||||
case _6:
|
||||
rm = 6;
|
||||
break;
|
||||
case _7:
|
||||
rm = 7;
|
||||
break;
|
||||
case _R:
|
||||
rm = (inst->rmode & (REG8 | REG16 | REG32)) ? rop.reg : lop.reg;
|
||||
break;
|
||||
}
|
||||
rm<<=3;
|
||||
if( mop.mode & REG ){ //reg
|
||||
emit( 0xc0|rm|mop.reg );
|
||||
}else if( mop.baseReg>=0 ){ //base, index?
|
||||
int mod=mop.offset ? 0x40 : 0x00;
|
||||
if( mop.baseLabel.size() || mop.offset<-128 || mop.offset>127 ) mod=0x80;
|
||||
if( mop.baseReg==5 && !mod ) mod=0x40;
|
||||
if( mop.indexReg>=0 ){ //base, index!
|
||||
emit( mod|rm|4 );
|
||||
emit( (mop.shift<<6)|(mop.indexReg<<3)|mop.baseReg );
|
||||
}else{ //base, no index!
|
||||
if( mop.baseReg!=4 ) emit( mod|rm|mop.baseReg);
|
||||
else{
|
||||
emit( mod|rm|4 );emit( (4<<3)|mop.baseReg );
|
||||
rm <<= 3;
|
||||
if (mop.mode & REG) { //reg
|
||||
emit(0xc0 | rm | mop.reg);
|
||||
} else if (mop.baseReg >= 0) { //base, index?
|
||||
int mod = mop.offset ? 0x40 : 0x00;
|
||||
if (mop.baseLabel.size() || mop.offset < -128 || mop.offset > 127)
|
||||
mod = 0x80;
|
||||
if (mop.baseReg == 5 && !mod)
|
||||
mod = 0x40;
|
||||
if (mop.indexReg >= 0) { //base, index!
|
||||
emit(mod | rm | 4);
|
||||
emit((mop.shift << 6) | (mop.indexReg << 3) | mop.baseReg);
|
||||
} else { //base, no index!
|
||||
if (mop.baseReg != 4)
|
||||
emit(mod | rm | mop.baseReg);
|
||||
else {
|
||||
emit(mod | rm | 4);
|
||||
emit((4 << 3) | mop.baseReg);
|
||||
}
|
||||
}
|
||||
if( (mod&0xc0)==0x40 ) emit( mop.offset );
|
||||
else if( (mod&0xc0)==0x80 ){
|
||||
if ((mod & 0xc0) == 0x40)
|
||||
emit(mop.offset);
|
||||
else if ((mod & 0xc0) == 0x80) {
|
||||
//reloc
|
||||
a_reloc( mop.baseLabel );emitd( mop.offset );
|
||||
a_reloc(mop.baseLabel);
|
||||
emitd(mop.offset);
|
||||
}
|
||||
}else if( mop.indexReg>=0 ){ //index, no base!
|
||||
emit( rm|4 );
|
||||
emit( (mop.shift<<6)|(mop.indexReg<<3)|5 );
|
||||
} else if (mop.indexReg >= 0) { //index, no base!
|
||||
emit(rm | 4);
|
||||
emit((mop.shift << 6) | (mop.indexReg << 3) | 5);
|
||||
//reloc
|
||||
a_reloc( mop.baseLabel );emitd( mop.offset );
|
||||
}else{ //[disp]
|
||||
emit( rm|5 );
|
||||
a_reloc(mop.baseLabel);
|
||||
emitd(mop.offset);
|
||||
} else { //[disp]
|
||||
emit(rm | 5);
|
||||
//reloc
|
||||
a_reloc( mop.baseLabel );emitd( mop.offset );
|
||||
a_reloc(mop.baseLabel);
|
||||
emitd(mop.offset);
|
||||
}
|
||||
}
|
||||
|
||||
if( inst->flags&RW_RD ){
|
||||
r_reloc( lop.immLabel );emitd( lop.imm-4 );
|
||||
if (inst->flags & RW_RD) {
|
||||
r_reloc(lop.immLabel);
|
||||
emitd(lop.imm - 4);
|
||||
}
|
||||
|
||||
if( inst->flags&IB ){
|
||||
if( lop.mode&IMM ) emitImm( lop,1 );else emitImm( rop,1 );
|
||||
}else if( inst->flags&IW ){
|
||||
if( lop.mode&IMM ) emitImm( lop,2 );else emitImm( rop,2 );
|
||||
}else if( inst->flags&ID ){
|
||||
if( lop.mode&IMM ) emitImm( lop,4 );else emitImm( rop,4 );
|
||||
if (inst->flags & IB) {
|
||||
if (lop.mode & IMM)
|
||||
emitImm(lop, 1);
|
||||
else
|
||||
emitImm(rop, 1);
|
||||
} else if (inst->flags & IW) {
|
||||
if (lop.mode & IMM)
|
||||
emitImm(lop, 2);
|
||||
else
|
||||
emitImm(rop, 2);
|
||||
} else if (inst->flags & ID) {
|
||||
if (lop.mode & IMM)
|
||||
emitImm(lop, 4);
|
||||
else
|
||||
emitImm(rop, 4);
|
||||
}
|
||||
}
|
||||
|
||||
void Assem_x86::assemDir( const string &name,const string &op ){
|
||||
void Assem_x86::assemDir(const string& name, const string& op)
|
||||
{
|
||||
if (!op.size())
|
||||
throw Ex("operand error");
|
||||
|
||||
if( !op.size() ) throw Ex( "operand error" );
|
||||
|
||||
if( name==".db" ){
|
||||
if( op[0]!='\"' ) emitImm( op,1 );
|
||||
else{
|
||||
if( op.size()<2 || op[op.size()-1]!='\"' ) throw Ex( "operand error" );
|
||||
for( int k=1;k<op.size()-1;++k ) emit( op[k] );
|
||||
if (name == ".db") {
|
||||
if (op[0] != '\"')
|
||||
emitImm(op, 1);
|
||||
else {
|
||||
if (op.size() < 2 || op[op.size() - 1] != '\"')
|
||||
throw Ex("operand error");
|
||||
for (int k = 1; k < op.size() - 1; ++k)
|
||||
emit(op[k]);
|
||||
}
|
||||
}else if( name==".dw" ){
|
||||
emitImm( op,2 );
|
||||
}else if( name==".dd" ){
|
||||
emitImm( op,4 );
|
||||
}else if( name==".align" ){
|
||||
Operand o( op );o.parse();
|
||||
if( !(o.mode&IMM) ) throw Ex( "operand must be immediate" );
|
||||
align( o.imm );
|
||||
}else{
|
||||
throw Ex( "unrecognized assembler directive" );
|
||||
} else if (name == ".dw") {
|
||||
emitImm(op, 2);
|
||||
} else if (name == ".dd") {
|
||||
emitImm(op, 4);
|
||||
} else if (name == ".align") {
|
||||
Operand o(op);
|
||||
o.parse();
|
||||
if (!(o.mode & IMM))
|
||||
throw Ex("operand must be immediate");
|
||||
align(o.imm);
|
||||
} else {
|
||||
throw Ex("unrecognized assembler directive");
|
||||
}
|
||||
}
|
||||
|
||||
void Assem_x86::assemLine( const string &line ){
|
||||
|
||||
int i=0;
|
||||
string name;
|
||||
void Assem_x86::assemLine(const string& line)
|
||||
{
|
||||
int i = 0;
|
||||
string name;
|
||||
vector<string> ops;
|
||||
|
||||
//label?
|
||||
if( !isspace( line[i] ) ){
|
||||
while( !isspace( line[i] ) ) ++i;
|
||||
string lab=line.substr( 0,i );
|
||||
if( !mod->addSymbol( lab.c_str(),mod->getPC() ) ) throw Ex( "duplicate label" );
|
||||
if (!isspace(line[i])) {
|
||||
while (!isspace(line[i]))
|
||||
++i;
|
||||
string lab = line.substr(0, i);
|
||||
if (!mod->addSymbol(lab.c_str(), mod->getPC()))
|
||||
throw Ex("duplicate label");
|
||||
}
|
||||
|
||||
//skip space
|
||||
while( isspace( line[i] ) && line[i]!='\n' ) ++i;
|
||||
if( line[i]=='\n' || line[i]==';' ) return;
|
||||
while (isspace(line[i]) && line[i] != '\n')
|
||||
++i;
|
||||
if (line[i] == '\n' || line[i] == ';')
|
||||
return;
|
||||
|
||||
//fetch instruction name
|
||||
int from=i;for( ++i;!isspace( line[i] );++i ){}
|
||||
name=line.substr( from,i-from );
|
||||
|
||||
for(;;){
|
||||
int from = i;
|
||||
for (++i; !isspace(line[i]); ++i) {
|
||||
}
|
||||
name = line.substr(from, i - from);
|
||||
|
||||
for (;;) {
|
||||
//skip space
|
||||
while( isspace( line[i] ) && line[i]!='\n' ) ++i;
|
||||
if( line[i]=='\n' || line[i]==';' ) break;
|
||||
while (isspace(line[i]) && line[i] != '\n')
|
||||
++i;
|
||||
if (line[i] == '\n' || line[i] == ';')
|
||||
break;
|
||||
|
||||
int from=i;
|
||||
if( line[i]=='\"' ){
|
||||
for( ++i;line[i]!='\"' && line[i]!='\n';++i ){}
|
||||
if( line[i++]!='\"' ) throw Ex( "missing close quote" );
|
||||
}else{
|
||||
for( ++i;line[i]!=',' && line[i]!=';' && line[i]!='\n';++i ){}
|
||||
int from = i;
|
||||
if (line[i] == '\"') {
|
||||
for (++i; line[i] != '\"' && line[i] != '\n'; ++i) {
|
||||
}
|
||||
if (line[i++] != '\"')
|
||||
throw Ex("missing close quote");
|
||||
} else {
|
||||
for (++i; line[i] != ',' && line[i] != ';' && line[i] != '\n'; ++i) {
|
||||
}
|
||||
}
|
||||
|
||||
//back-up over space
|
||||
while( i && isspace( line[i-1] ) ) --i;
|
||||
ops.push_back( line.substr( from,i-from ) );
|
||||
while (i && isspace(line[i - 1]))
|
||||
--i;
|
||||
ops.push_back(line.substr(from, i - from));
|
||||
|
||||
//skip space
|
||||
while( isspace( line[i] ) && line[i]!='\n' ) ++i;
|
||||
if( line[i]=='\n' || line[i]==';' ) break;
|
||||
while (isspace(line[i]) && line[i] != '\n')
|
||||
++i;
|
||||
if (line[i] == '\n' || line[i] == ';')
|
||||
break;
|
||||
|
||||
if( line[i++]!=',' ) throw Ex( "expecting ','" );
|
||||
if (line[i++] != ',')
|
||||
throw Ex("expecting ','");
|
||||
}
|
||||
|
||||
//pseudo op?
|
||||
if( name[0]=='.' ){
|
||||
for( int k=0;k<ops.size();++k ) assemDir( name,ops[k] );
|
||||
if (name[0] == '.') {
|
||||
for (int k = 0; k < ops.size(); ++k)
|
||||
assemDir(name, ops[k]);
|
||||
return;
|
||||
}
|
||||
|
||||
//normal instruction!
|
||||
if( ops.size()>2 ) throw Ex( "Too many operands" );
|
||||
ops.push_back( "" );ops.push_back( "" );
|
||||
assemInst( name,ops[0],ops[1] );
|
||||
if (ops.size() > 2)
|
||||
throw Ex("Too many operands");
|
||||
ops.push_back("");
|
||||
ops.push_back("");
|
||||
assemInst(name, ops[0], ops[1]);
|
||||
}
|
||||
|
||||
void Assem_x86::assemble(){
|
||||
|
||||
void Assem_x86::assemble()
|
||||
{
|
||||
string line;
|
||||
|
||||
while( !in.eof() ){
|
||||
try{
|
||||
getline( in,line );
|
||||
line+='\n';
|
||||
while (!in.eof()) {
|
||||
try {
|
||||
getline(in, line);
|
||||
line += '\n';
|
||||
#ifdef LOG
|
||||
clog<<line;
|
||||
clog << line;
|
||||
#endif
|
||||
assemLine( line );
|
||||
assemLine(line);
|
||||
#ifdef LOG
|
||||
clog<<endl;
|
||||
clog << endl;
|
||||
#endif
|
||||
}catch( Ex &x ){
|
||||
throw Ex( line+x.ex );
|
||||
} catch (Ex& x) {
|
||||
throw Ex(line + x.ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+183
-117
@@ -1,160 +1,226 @@
|
||||
|
||||
#include "../std.h"
|
||||
#include "../ex.h"
|
||||
#include "operand.h"
|
||||
#include "../ex.h"
|
||||
#include "../std.h"
|
||||
#include "insts.h"
|
||||
|
||||
static const char *regs[]={
|
||||
"al","cl","dl","bl","ah","ch","dh","bh",
|
||||
"ax","cx","dx","bx","sp","bp","si","di",
|
||||
"eax","ecx","edx","ebx","esp","ebp","esi","edi"
|
||||
};
|
||||
static const char* regs[] = {"al", "cl", "dl", "bl", "ah", "ch", "dh", "bh", "ax", "cx", "dx", "bx",
|
||||
"sp", "bp", "si", "di", "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi"};
|
||||
|
||||
static void opError(){
|
||||
throw Ex( "error in operand" );
|
||||
static void opError()
|
||||
{
|
||||
throw Ex("error in operand");
|
||||
}
|
||||
|
||||
static void sizeError(){
|
||||
throw Ex( "illegal operand size" );
|
||||
static void sizeError()
|
||||
{
|
||||
throw Ex("illegal operand size");
|
||||
}
|
||||
|
||||
Operand::Operand()
|
||||
:mode(NONE),reg(-1),imm(0),offset(0),baseReg(-1),indexReg(-1),shift(0){
|
||||
}
|
||||
Operand::Operand() : mode(NONE), reg(-1), imm(0), offset(0), baseReg(-1), indexReg(-1), shift(0) {}
|
||||
|
||||
Operand::Operand( const string &s )
|
||||
:mode(NONE),reg(-1),imm(0),offset(0),baseReg(-1),indexReg(-1),shift(0),s(s){
|
||||
}
|
||||
Operand::Operand(const string& s) : mode(NONE), reg(-1), imm(0), offset(0), baseReg(-1), indexReg(-1), shift(0), s(s) {}
|
||||
|
||||
bool Operand::parseSize( int *sz ){
|
||||
|
||||
if( !s.size() ) return false;
|
||||
if( s.find( "byte " )==0 ){
|
||||
*sz=1;s=s.substr( 5 );
|
||||
}else if( s.find( "word " )==0 ){
|
||||
*sz=2;s=s.substr( 5 );
|
||||
}else if( s.find( "dword " )==0 ){
|
||||
*sz=4;s=s.substr( 6 );
|
||||
}else return false;
|
||||
bool Operand::parseSize(int* sz)
|
||||
{
|
||||
if (!s.size())
|
||||
return false;
|
||||
if (s.find("byte ") == 0) {
|
||||
*sz = 1;
|
||||
s = s.substr(5);
|
||||
} else if (s.find("word ") == 0) {
|
||||
*sz = 2;
|
||||
s = s.substr(5);
|
||||
} else if (s.find("dword ") == 0) {
|
||||
*sz = 4;
|
||||
s = s.substr(6);
|
||||
} else
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Operand::parseChar( char c ){
|
||||
if( !s.size() || s[0]!=c ) return false;
|
||||
s=s.substr( 1 );return true;
|
||||
bool Operand::parseChar(char c)
|
||||
{
|
||||
if (!s.size() || s[0] != c)
|
||||
return false;
|
||||
s = s.substr(1);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Operand::parseReg( int *reg ){
|
||||
bool Operand::parseReg(int* reg)
|
||||
{
|
||||
int i;
|
||||
for( i=0;i<s.size() && isalpha( s[i] );++i ){}
|
||||
if( !i ) return false;
|
||||
string t=s.substr(0,i);
|
||||
for( int j=0;j<24;++j ){
|
||||
if( t==regs[j] ){ *reg=j;s=s.substr( i );return true; }
|
||||
for (i = 0; i < s.size() && isalpha(s[i]); ++i) {
|
||||
}
|
||||
if (!i)
|
||||
return false;
|
||||
string t = s.substr(0, i);
|
||||
for (int j = 0; j < 24; ++j) {
|
||||
if (t == regs[j]) {
|
||||
*reg = j;
|
||||
s = s.substr(i);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Operand::parseFPReg( int *reg ){
|
||||
|
||||
bool Operand::parseFPReg(int* reg)
|
||||
{
|
||||
//eg: st(0)
|
||||
if( s.size()<5 ) return false;
|
||||
if( s[0]!='s' || s[1]!='t' || s[2]!='(' || s[4]!=')' ) return false;
|
||||
if( s[3]<'0' || s[3]>'7' ) return false;
|
||||
*reg=s[3]-'0';s=s.substr( 5 );return true;
|
||||
if (s.size() < 5)
|
||||
return false;
|
||||
if (s[0] != 's' || s[1] != 't' || s[2] != '(' || s[4] != ')')
|
||||
return false;
|
||||
if (s[3] < '0' || s[3] > '7')
|
||||
return false;
|
||||
*reg = s[3] - '0';
|
||||
s = s.substr(5);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Operand::parseLabel( string *label ){
|
||||
if( !s.size() || (!isalpha( s[0] ) && s[0]!='_') ) return false;
|
||||
bool Operand::parseLabel(string* label)
|
||||
{
|
||||
if (!s.size() || (!isalpha(s[0]) && s[0] != '_'))
|
||||
return false;
|
||||
int i;
|
||||
for( i=1;i<s.size() && (isalnum( s[i] ) || s[i]=='_');++i ){}
|
||||
*label=s.substr(0,i);s=s.substr( i );return true;
|
||||
for (i = 1; i < s.size() && (isalnum(s[i]) || s[i] == '_'); ++i) {
|
||||
}
|
||||
*label = s.substr(0, i);
|
||||
s = s.substr(i);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Operand::parseConst( int *iconst ){
|
||||
int i,sgn=s.size() && (s[0]=='-'||s[0]=='+');
|
||||
for( i=sgn;i<s.size() && isdigit( s[i] );++i ){}
|
||||
if( i==sgn ) return false;
|
||||
int n=atoi( s.c_str() );
|
||||
*iconst=n;s=s.substr( i );return true;
|
||||
bool Operand::parseConst(int* iconst)
|
||||
{
|
||||
int i, sgn = s.size() && (s[0] == '-' || s[0] == '+');
|
||||
for (i = sgn; i < s.size() && isdigit(s[i]); ++i) {
|
||||
}
|
||||
if (i == sgn)
|
||||
return false;
|
||||
int n = atoi(s.c_str());
|
||||
*iconst = n;
|
||||
s = s.substr(i);
|
||||
return true;
|
||||
}
|
||||
|
||||
void Operand::parse(){
|
||||
void Operand::parse()
|
||||
{
|
||||
if (!s.size())
|
||||
return;
|
||||
|
||||
if( !s.size() ) return;
|
||||
int sz;
|
||||
if (!parseSize(&sz))
|
||||
sz = 0;
|
||||
|
||||
int sz;if( !parseSize( &sz ) ) sz=0;
|
||||
|
||||
if( s[0]!='[' ){
|
||||
if (s[0] != '[') {
|
||||
int r;
|
||||
if( parseReg( &r ) ){
|
||||
mode=REG|R_M;
|
||||
if( r<8 ){
|
||||
if( sz && sz!=1 ) sizeError();
|
||||
mode|=REG8|R_M8;
|
||||
if( r==0 ) mode|=AL;else if( r==1 ) mode|=CL;
|
||||
}else if( r<16 ){
|
||||
if( sz && sz!=2 ) sizeError();
|
||||
mode|=REG16|R_M16;
|
||||
if( r==8 ) mode|=AX;else if( r==9 ) mode|=CX;
|
||||
}else{
|
||||
if( sz && sz!=4 ) sizeError();
|
||||
mode|=REG32|R_M32;
|
||||
if( r==16 ) mode|=EAX;else if( r==17 ) mode|=ECX;
|
||||
if (parseReg(&r)) {
|
||||
mode = REG | R_M;
|
||||
if (r < 8) {
|
||||
if (sz && sz != 1)
|
||||
sizeError();
|
||||
mode |= REG8 | R_M8;
|
||||
if (r == 0)
|
||||
mode |= AL;
|
||||
else if (r == 1)
|
||||
mode |= CL;
|
||||
} else if (r < 16) {
|
||||
if (sz && sz != 2)
|
||||
sizeError();
|
||||
mode |= REG16 | R_M16;
|
||||
if (r == 8)
|
||||
mode |= AX;
|
||||
else if (r == 9)
|
||||
mode |= CX;
|
||||
} else {
|
||||
if (sz && sz != 4)
|
||||
sizeError();
|
||||
mode |= REG32 | R_M32;
|
||||
if (r == 16)
|
||||
mode |= EAX;
|
||||
else if (r == 17)
|
||||
mode |= ECX;
|
||||
}
|
||||
reg=r&7;
|
||||
}else if( parseFPReg( &r ) ){
|
||||
mode=FPUREG;
|
||||
if( !r ) mode|=ST0;
|
||||
reg=r;
|
||||
}else if( parseLabel( &immLabel ) ){
|
||||
if( sz && sz!=4 ) sizeError();
|
||||
mode=IMM|IMM32;
|
||||
}else if( parseConst( &imm ) ){
|
||||
mode=IMM;
|
||||
if( sz==1 ) mode|=IMM8;
|
||||
else if( sz==2 ) mode|=IMM16;
|
||||
else mode|=IMM32;
|
||||
}else opError();
|
||||
if( s.size() ) opError();
|
||||
reg = r & 7;
|
||||
} else if (parseFPReg(&r)) {
|
||||
mode = FPUREG;
|
||||
if (!r)
|
||||
mode |= ST0;
|
||||
reg = r;
|
||||
} else if (parseLabel(&immLabel)) {
|
||||
if (sz && sz != 4)
|
||||
sizeError();
|
||||
mode = IMM | IMM32;
|
||||
} else if (parseConst(&imm)) {
|
||||
mode = IMM;
|
||||
if (sz == 1)
|
||||
mode |= IMM8;
|
||||
else if (sz == 2)
|
||||
mode |= IMM16;
|
||||
else
|
||||
mode |= IMM32;
|
||||
} else
|
||||
opError();
|
||||
if (s.size())
|
||||
opError();
|
||||
return;
|
||||
}
|
||||
|
||||
if( s[s.size()-1]!=']' ) opError();
|
||||
s=s.substr( 1,s.size()-2 );
|
||||
if (s[s.size() - 1] != ']')
|
||||
opError();
|
||||
s = s.substr(1, s.size() - 2);
|
||||
|
||||
mode=MEM|R_M;
|
||||
if( sz==1 ) mode|=MEM8|R_M8;
|
||||
else if( sz==2 ) mode|=MEM16|R_M16;
|
||||
else mode|=MEM32|R_M32;
|
||||
mode = MEM | R_M;
|
||||
if (sz == 1)
|
||||
mode |= MEM8 | R_M8;
|
||||
else if (sz == 2)
|
||||
mode |= MEM16 | R_M16;
|
||||
else
|
||||
mode |= MEM32 | R_M32;
|
||||
|
||||
for(;;){
|
||||
int n;string l;
|
||||
if( parseReg( &n ) ){
|
||||
if( n<16 ) throw Ex( "register must be 32 bit" );
|
||||
n&=7;
|
||||
if( parseChar( '*' ) ){
|
||||
if( n==4 ) break; //esp cannot be index reg!
|
||||
if( indexReg>=0 ) break;
|
||||
if( parseChar( '1' ) ) shift=0;
|
||||
else if( parseChar( '2' ) ) shift=1;
|
||||
else if( parseChar( '4' ) ) shift=2;
|
||||
else if( parseChar( '8' ) ) shift=3;
|
||||
else break;
|
||||
indexReg=n;
|
||||
}else{
|
||||
if( baseReg<0 ) baseReg=n;
|
||||
else if( indexReg<0 ){ indexReg=n; }
|
||||
else break;
|
||||
for (;;) {
|
||||
int n;
|
||||
string l;
|
||||
if (parseReg(&n)) {
|
||||
if (n < 16)
|
||||
throw Ex("register must be 32 bit");
|
||||
n &= 7;
|
||||
if (parseChar('*')) {
|
||||
if (n == 4)
|
||||
break; //esp cannot be index reg!
|
||||
if (indexReg >= 0)
|
||||
break;
|
||||
if (parseChar('1'))
|
||||
shift = 0;
|
||||
else if (parseChar('2'))
|
||||
shift = 1;
|
||||
else if (parseChar('4'))
|
||||
shift = 2;
|
||||
else if (parseChar('8'))
|
||||
shift = 3;
|
||||
else
|
||||
break;
|
||||
indexReg = n;
|
||||
} else {
|
||||
if (baseReg < 0)
|
||||
baseReg = n;
|
||||
else if (indexReg < 0) {
|
||||
indexReg = n;
|
||||
} else
|
||||
break;
|
||||
}
|
||||
}else if( parseLabel( &l ) ){
|
||||
if( baseLabel.size() ) opError();
|
||||
baseLabel=l;
|
||||
}else if( parseConst( &n ) ){
|
||||
offset+=n;
|
||||
}else break;
|
||||
if( !s.size() ) return;
|
||||
} else if (parseLabel(&l)) {
|
||||
if (baseLabel.size())
|
||||
opError();
|
||||
baseLabel = l;
|
||||
} else if (parseConst(&n)) {
|
||||
offset += n;
|
||||
} else
|
||||
break;
|
||||
if (!s.size())
|
||||
return;
|
||||
}
|
||||
opError();
|
||||
}
|
||||
|
||||
+75
-34
@@ -4,52 +4,93 @@
|
||||
|
||||
#include "std.hpp"
|
||||
|
||||
enum{
|
||||
IR_JUMP,IR_JUMPT,IR_JUMPF,IR_JUMPGE,
|
||||
enum {
|
||||
IR_JUMP,
|
||||
IR_JUMPT,
|
||||
IR_JUMPF,
|
||||
IR_JUMPGE,
|
||||
|
||||
IR_SEQ,IR_MOVE,IR_MEM,IR_LOCAL,IR_GLOBAL,IR_ARG,IR_CONST,
|
||||
IR_SEQ,
|
||||
IR_MOVE,
|
||||
IR_MEM,
|
||||
IR_LOCAL,
|
||||
IR_GLOBAL,
|
||||
IR_ARG,
|
||||
IR_CONST,
|
||||
|
||||
IR_JSR,IR_RET,IR_AND,IR_OR,IR_XOR,IR_SHL,IR_SHR,IR_SAR,
|
||||
IR_JSR,
|
||||
IR_RET,
|
||||
IR_AND,
|
||||
IR_OR,
|
||||
IR_XOR,
|
||||
IR_SHL,
|
||||
IR_SHR,
|
||||
IR_SAR,
|
||||
|
||||
IR_CALL,IR_RETURN,IR_CAST,
|
||||
IR_NEG,IR_ADD,IR_SUB,IR_MUL,IR_DIV,
|
||||
IR_SETEQ,IR_SETNE,IR_SETLT,IR_SETGT,IR_SETLE,IR_SETGE,
|
||||
IR_CALL,
|
||||
IR_RETURN,
|
||||
IR_CAST,
|
||||
IR_NEG,
|
||||
IR_ADD,
|
||||
IR_SUB,
|
||||
IR_MUL,
|
||||
IR_DIV,
|
||||
IR_SETEQ,
|
||||
IR_SETNE,
|
||||
IR_SETLT,
|
||||
IR_SETGT,
|
||||
IR_SETLE,
|
||||
IR_SETGE,
|
||||
|
||||
IR_FCALL,IR_FRETURN,IR_FCAST,
|
||||
IR_FNEG,IR_FADD,IR_FSUB,IR_FMUL,IR_FDIV,
|
||||
IR_FSETEQ,IR_FSETNE,IR_FSETLT,IR_FSETGT,IR_FSETLE,IR_FSETGE,
|
||||
IR_FCALL,
|
||||
IR_FRETURN,
|
||||
IR_FCAST,
|
||||
IR_FNEG,
|
||||
IR_FADD,
|
||||
IR_FSUB,
|
||||
IR_FMUL,
|
||||
IR_FDIV,
|
||||
IR_FSETEQ,
|
||||
IR_FSETNE,
|
||||
IR_FSETLT,
|
||||
IR_FSETGT,
|
||||
IR_FSETLE,
|
||||
IR_FSETGE,
|
||||
};
|
||||
|
||||
struct TNode{
|
||||
struct TNode {
|
||||
int op; //opcode
|
||||
TNode *l, *r; //args
|
||||
int iconst; //for CONST type_int
|
||||
string sconst; //for CONST type_string
|
||||
|
||||
int op; //opcode
|
||||
TNode *l,*r; //args
|
||||
int iconst; //for CONST type_int
|
||||
string sconst; //for CONST type_string
|
||||
|
||||
TNode( int op,TNode *l=0,TNode *r=0 ):op(op),l(l),r(r),iconst(0){}
|
||||
TNode( int op,TNode *l,TNode *r,int i ):op(op),l(l),r(r),iconst(i){}
|
||||
TNode( int op,TNode *l,TNode *r,const string &s ):op(op),l(l),r(r),iconst(0),sconst(s){}
|
||||
~TNode(){ delete l;delete r; }
|
||||
TNode(int op, TNode* l = 0, TNode* r = 0) : op(op), l(l), r(r), iconst(0) {}
|
||||
TNode(int op, TNode* l, TNode* r, int i) : op(op), l(l), r(r), iconst(i) {}
|
||||
TNode(int op, TNode* l, TNode* r, const string& s) : op(op), l(l), r(r), iconst(0), sconst(s) {}
|
||||
~TNode()
|
||||
{
|
||||
delete l;
|
||||
delete r;
|
||||
}
|
||||
|
||||
void log();
|
||||
};
|
||||
|
||||
class Codegen{
|
||||
public:
|
||||
ostream &out;
|
||||
bool debug;
|
||||
Codegen( ostream &out,bool debug ):out( out ),debug( debug ){}
|
||||
class Codegen {
|
||||
public:
|
||||
ostream& out;
|
||||
bool debug;
|
||||
Codegen(ostream& out, bool debug) : out(out), debug(debug) {}
|
||||
|
||||
virtual void enter( const string &l,int frameSize )=0;
|
||||
virtual void code( TNode *code )=0;
|
||||
virtual void leave( TNode *cleanup,int pop_sz )=0;
|
||||
virtual void label( const string &l )=0;
|
||||
virtual void i_data( int i,const string &l="" )=0;
|
||||
virtual void s_data( const string &s,const string &l="" )=0;
|
||||
virtual void p_data( const string &p,const string &l="" )=0;
|
||||
virtual void align_data( int n )=0;
|
||||
virtual void flush()=0;
|
||||
virtual void enter(const string& l, int frameSize) = 0;
|
||||
virtual void code(TNode* code) = 0;
|
||||
virtual void leave(TNode* cleanup, int pop_sz) = 0;
|
||||
virtual void label(const string& l) = 0;
|
||||
virtual void i_data(int i, const string& l = "") = 0;
|
||||
virtual void s_data(const string& s, const string& l = "") = 0;
|
||||
virtual void p_data(const string& p, const string& l = "") = 0;
|
||||
virtual void align_data(int n) = 0;
|
||||
virtual void flush() = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,425 +1,563 @@
|
||||
|
||||
#include "../std.h"
|
||||
#include "codegen_x86.h"
|
||||
#include "../std.h"
|
||||
#include "tile.h"
|
||||
|
||||
//#define NOOPTS
|
||||
|
||||
Codegen_x86::Codegen_x86( ostream &out,bool debug ):Codegen( out,debug ),inCode(false){
|
||||
Codegen_x86::Codegen_x86(ostream& out, bool debug) : Codegen(out, debug), inCode(false) {}
|
||||
|
||||
static string itoa_sgn(int n)
|
||||
{
|
||||
return n ? (n > 0 ? "+" + itoa(n) : itoa(n)) : "";
|
||||
}
|
||||
|
||||
static string itoa_sgn(int n){
|
||||
return n ? (n>0 ? "+"+itoa(n) : itoa(n)) : "";
|
||||
static bool isRelop(int op)
|
||||
{
|
||||
return op == IR_SETEQ || op == IR_SETNE || op == IR_SETLT || op == IR_SETGT || op == IR_SETLE || op == IR_SETGE;
|
||||
}
|
||||
|
||||
static bool isRelop( int op ){
|
||||
return op==IR_SETEQ||op==IR_SETNE||op==IR_SETLT||op==IR_SETGT||op==IR_SETLE||op==IR_SETGE;
|
||||
}
|
||||
static bool nodesEqual(TNode* t1, TNode* t2)
|
||||
{
|
||||
if (t1->op != t2->op || t1->iconst != t2->iconst || t1->sconst != t2->sconst)
|
||||
return false;
|
||||
|
||||
static bool nodesEqual( TNode *t1,TNode *t2 ){
|
||||
if( t1->op!=t2->op ||
|
||||
t1->iconst!=t2->iconst ||
|
||||
t1->sconst!=t2->sconst ) return false;
|
||||
if (t1->l) {
|
||||
if (!t2->l || !nodesEqual(t1->l, t2->l))
|
||||
return false;
|
||||
} else if (t2->l)
|
||||
return false;
|
||||
|
||||
if( t1->l ){
|
||||
if( !t2->l || !nodesEqual( t1->l,t2->l ) ) return false;
|
||||
}else if( t2->l ) return false;
|
||||
|
||||
if( t1->r ){
|
||||
if( !t2->r || !nodesEqual( t1->r,t2->r ) ) return false;
|
||||
}else if( t2->r ) return false;
|
||||
if (t1->r) {
|
||||
if (!t2->r || !nodesEqual(t1->r, t2->r))
|
||||
return false;
|
||||
} else if (t2->r)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool getShift( int n,int &shift ){
|
||||
static bool getShift(int n, int& shift)
|
||||
{
|
||||
#ifdef NOOPTS
|
||||
return false;
|
||||
#endif
|
||||
|
||||
for( shift=0;shift<32;++shift ){
|
||||
if( (1<<shift)==n ) return true;
|
||||
for (shift = 0; shift < 32; ++shift) {
|
||||
if ((1 << shift) == n)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool matchMEM( TNode *t,string &s ){
|
||||
static bool matchMEM(TNode* t, string& s)
|
||||
{
|
||||
#ifdef NOOPTS
|
||||
return false;
|
||||
#endif
|
||||
|
||||
if( t->op!=IR_MEM ) return false;
|
||||
t=t->l;
|
||||
switch( t->op ){
|
||||
case IR_GLOBAL:s="["+t->sconst+"]";return true;
|
||||
case IR_LOCAL:s="[ebp"+itoa_sgn(t->iconst)+"]";return true;
|
||||
case IR_ARG:s="[esp"+itoa_sgn(t->iconst)+"]";return true;
|
||||
if (t->op != IR_MEM)
|
||||
return false;
|
||||
t = t->l;
|
||||
switch (t->op) {
|
||||
case IR_GLOBAL:
|
||||
s = "[" + t->sconst + "]";
|
||||
return true;
|
||||
case IR_LOCAL:
|
||||
s = "[ebp" + itoa_sgn(t->iconst) + "]";
|
||||
return true;
|
||||
case IR_ARG:
|
||||
s = "[esp" + itoa_sgn(t->iconst) + "]";
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool matchCONST( TNode *t,string &s ){
|
||||
static bool matchCONST(TNode* t, string& s)
|
||||
{
|
||||
#ifdef NOOPTS
|
||||
return false;
|
||||
#endif
|
||||
|
||||
switch( t->op ){
|
||||
case IR_CONST:s=itoa( t->iconst );return true;
|
||||
case IR_GLOBAL:s=t->sconst;return true;
|
||||
switch (t->op) {
|
||||
case IR_CONST:
|
||||
s = itoa(t->iconst);
|
||||
return true;
|
||||
case IR_GLOBAL:
|
||||
s = t->sconst;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool matchMEMCONST( TNode *t,string &s ){
|
||||
static bool matchMEMCONST(TNode* t, string& s)
|
||||
{
|
||||
#ifdef NOOPTS
|
||||
return false;
|
||||
#endif
|
||||
|
||||
return matchMEM( t,s ) || matchCONST( t,s );
|
||||
return matchMEM(t, s) || matchCONST(t, s);
|
||||
}
|
||||
|
||||
Tile *Codegen_x86::genCompare( TNode *t,string &func,bool negate ){
|
||||
|
||||
switch( t->op ){
|
||||
case IR_SETEQ:func=negate ? "nz" : "z";break;
|
||||
case IR_SETNE:func=negate ? "z" : "nz";break;
|
||||
case IR_SETLT:func=negate ? "ge" : "l";break;
|
||||
case IR_SETGT:func=negate ? "le" : "g";break;
|
||||
case IR_SETLE:func=negate ? "g" : "le";break;
|
||||
case IR_SETGE:func=negate ? "l" : "ge";break;
|
||||
default:return 0;
|
||||
Tile* Codegen_x86::genCompare(TNode* t, string& func, bool negate)
|
||||
{
|
||||
switch (t->op) {
|
||||
case IR_SETEQ:
|
||||
func = negate ? "nz" : "z";
|
||||
break;
|
||||
case IR_SETNE:
|
||||
func = negate ? "z" : "nz";
|
||||
break;
|
||||
case IR_SETLT:
|
||||
func = negate ? "ge" : "l";
|
||||
break;
|
||||
case IR_SETGT:
|
||||
func = negate ? "le" : "g";
|
||||
break;
|
||||
case IR_SETLE:
|
||||
func = negate ? "g" : "le";
|
||||
break;
|
||||
case IR_SETGE:
|
||||
func = negate ? "l" : "ge";
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
string q,m,c;
|
||||
TNode *ql=0,*qr=0;
|
||||
string q, m, c;
|
||||
TNode *ql = 0, *qr = 0;
|
||||
|
||||
if( matchMEM( t->l,m ) ){
|
||||
if( matchCONST( t->r,c ) ){
|
||||
q="\tcmp\t"+m+","+c+"\n";
|
||||
}else{
|
||||
q="\tcmp\t"+m+",%l\n";ql=t->r;
|
||||
if (matchMEM(t->l, m)) {
|
||||
if (matchCONST(t->r, c)) {
|
||||
q = "\tcmp\t" + m + "," + c + "\n";
|
||||
} else {
|
||||
q = "\tcmp\t" + m + ",%l\n";
|
||||
ql = t->r;
|
||||
}
|
||||
}else{
|
||||
if( matchMEMCONST( t->r,m ) ){
|
||||
q="\tcmp\t%l,"+m+"\n";ql=t->l;
|
||||
}else{
|
||||
q="\tcmp\t%l,%r\n";ql=t->l;qr=t->r;
|
||||
} else {
|
||||
if (matchMEMCONST(t->r, m)) {
|
||||
q = "\tcmp\t%l," + m + "\n";
|
||||
ql = t->l;
|
||||
} else {
|
||||
q = "\tcmp\t%l,%r\n";
|
||||
ql = t->l;
|
||||
qr = t->r;
|
||||
}
|
||||
}
|
||||
|
||||
return new Tile( q,ql ? munchReg( ql ) : 0,qr ? munchReg( qr ) : 0 );
|
||||
return new Tile(q, ql ? munchReg(ql) : 0, qr ? munchReg(qr) : 0);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////
|
||||
// Integer expressions returned in a register //
|
||||
////////////////////////////////////////////////
|
||||
Tile *Codegen_x86::munchUnary( TNode *t ){
|
||||
Tile* Codegen_x86::munchUnary(TNode* t)
|
||||
{
|
||||
string s;
|
||||
switch( t->op ){
|
||||
case IR_NEG:s="\tneg\t%l\n";break;
|
||||
default:return 0;
|
||||
switch (t->op) {
|
||||
case IR_NEG:
|
||||
s = "\tneg\t%l\n";
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return new Tile( s,munchReg( t->l ) );
|
||||
return new Tile(s, munchReg(t->l));
|
||||
}
|
||||
|
||||
Tile *Codegen_x86::munchLogical( TNode *t ){
|
||||
Tile* Codegen_x86::munchLogical(TNode* t)
|
||||
{
|
||||
string s;
|
||||
switch( t->op ){
|
||||
case IR_AND:s="\tand\t%l,%r\n";break;
|
||||
case IR_OR:s="\tor\t%l,%r\n";break;
|
||||
case IR_XOR:s="\txor\t%l,%r\n";break;
|
||||
default:return 0;
|
||||
switch (t->op) {
|
||||
case IR_AND:
|
||||
s = "\tand\t%l,%r\n";
|
||||
break;
|
||||
case IR_OR:
|
||||
s = "\tor\t%l,%r\n";
|
||||
break;
|
||||
case IR_XOR:
|
||||
s = "\txor\t%l,%r\n";
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return new Tile( s,munchReg( t->l ),munchReg( t->r ) );
|
||||
return new Tile(s, munchReg(t->l), munchReg(t->r));
|
||||
}
|
||||
|
||||
Tile *Codegen_x86::munchArith( TNode *t ){
|
||||
|
||||
if( t->op==IR_DIV ){
|
||||
Tile* Codegen_x86::munchArith(TNode* t)
|
||||
{
|
||||
if (t->op == IR_DIV) {
|
||||
int shift;
|
||||
if( t->r->op==IR_CONST ){
|
||||
if( getShift( t->r->iconst,shift ) ){
|
||||
return new Tile( "\tsar\t%l,byte "+itoa(shift)+"\n",munchReg( t->l ) );
|
||||
if (t->r->op == IR_CONST) {
|
||||
if (getShift(t->r->iconst, shift)) {
|
||||
return new Tile("\tsar\t%l,byte " + itoa(shift) + "\n", munchReg(t->l));
|
||||
}
|
||||
}
|
||||
Tile *q=new Tile( "\tcdq\n\tidiv\tecx\n",munchReg( t->l ),munchReg( t->r ) );
|
||||
q->want_l=EAX;q->want_r=ECX;q->hits=1<<EDX;
|
||||
Tile* q = new Tile("\tcdq\n\tidiv\tecx\n", munchReg(t->l), munchReg(t->r));
|
||||
q->want_l = EAX;
|
||||
q->want_r = ECX;
|
||||
q->hits = 1 << EDX;
|
||||
return q;
|
||||
}
|
||||
|
||||
if( t->op==IR_MUL ){
|
||||
if (t->op == IR_MUL) {
|
||||
int shift;
|
||||
if( t->r->op==IR_CONST ){
|
||||
if( getShift( t->r->iconst,shift ) ){
|
||||
return new Tile( "\tshl\t%l,byte "+itoa(shift)+"\n",munchReg( t->l ) );
|
||||
if (t->r->op == IR_CONST) {
|
||||
if (getShift(t->r->iconst, shift)) {
|
||||
return new Tile("\tshl\t%l,byte " + itoa(shift) + "\n", munchReg(t->l));
|
||||
}
|
||||
}else if( t->l->op==IR_CONST ){
|
||||
if( getShift( t->l->iconst,shift ) ){
|
||||
return new Tile( "\tshl\t%l,byte "+itoa(shift)+"\n",munchReg( t->r ) );
|
||||
} else if (t->l->op == IR_CONST) {
|
||||
if (getShift(t->l->iconst, shift)) {
|
||||
return new Tile("\tshl\t%l,byte " + itoa(shift) + "\n", munchReg(t->r));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
string s,op;
|
||||
switch( t->op ){
|
||||
case IR_ADD:op="\tadd\t";break;
|
||||
case IR_SUB:op="\tsub\t";break;
|
||||
case IR_MUL:op="\timul\t";break;
|
||||
default:return 0;
|
||||
string s, op;
|
||||
switch (t->op) {
|
||||
case IR_ADD:
|
||||
op = "\tadd\t";
|
||||
break;
|
||||
case IR_SUB:
|
||||
op = "\tsub\t";
|
||||
break;
|
||||
case IR_MUL:
|
||||
op = "\timul\t";
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( matchMEMCONST( t->r,s ) ){
|
||||
return new Tile( op+"%l,"+s+"\n",munchReg( t->l ) );
|
||||
if (matchMEMCONST(t->r, s)) {
|
||||
return new Tile(op + "%l," + s + "\n", munchReg(t->l));
|
||||
}
|
||||
if( t->op!=IR_SUB && matchMEMCONST( t->l,s ) ){
|
||||
return new Tile( op+"%l,"+s+"\n",munchReg( t->r ) );
|
||||
if (t->op != IR_SUB && matchMEMCONST(t->l, s)) {
|
||||
return new Tile(op + "%l," + s + "\n", munchReg(t->r));
|
||||
}
|
||||
return new Tile( op+"%l,%r\n",munchReg( t->l ),munchReg( t->r ) );
|
||||
return new Tile(op + "%l,%r\n", munchReg(t->l), munchReg(t->r));
|
||||
}
|
||||
|
||||
Tile *Codegen_x86::munchShift( TNode *t ){
|
||||
string s,op;
|
||||
switch( t->op ){
|
||||
case IR_SHL:op="\tshl\t";break;
|
||||
case IR_SHR:op="\tshr\t";break;
|
||||
case IR_SAR:op="\tsar\t";break;
|
||||
default:return 0;
|
||||
Tile* Codegen_x86::munchShift(TNode* t)
|
||||
{
|
||||
string s, op;
|
||||
switch (t->op) {
|
||||
case IR_SHL:
|
||||
op = "\tshl\t";
|
||||
break;
|
||||
case IR_SHR:
|
||||
op = "\tshr\t";
|
||||
break;
|
||||
case IR_SAR:
|
||||
op = "\tsar\t";
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( matchCONST( t->r,s ) ){
|
||||
return new Tile( op+"%l,byte "+s+"\n",munchReg( t->l ) );
|
||||
if (matchCONST(t->r, s)) {
|
||||
return new Tile(op + "%l,byte " + s + "\n", munchReg(t->l));
|
||||
}
|
||||
|
||||
Tile *q=new Tile( op+"%l,cl\n",munchReg( t->l ),munchReg( t->r ) );
|
||||
q->want_r=ECX;return q;
|
||||
Tile* q = new Tile(op + "%l,cl\n", munchReg(t->l), munchReg(t->r));
|
||||
q->want_r = ECX;
|
||||
return q;
|
||||
}
|
||||
|
||||
Tile *Codegen_x86::munchRelop( TNode *t ){
|
||||
Tile* Codegen_x86::munchRelop(TNode* t)
|
||||
{
|
||||
string func;
|
||||
Tile *q=genCompare( t,func,false );
|
||||
Tile* q = genCompare(t, func, false);
|
||||
|
||||
q=new Tile( "\tset"+func+"\tal\n\tmovzx\teax,al\n",q );
|
||||
q->want_l=EAX;
|
||||
q = new Tile("\tset" + func + "\tal\n\tmovzx\teax,al\n", q);
|
||||
q->want_l = EAX;
|
||||
return q;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////
|
||||
// Float expressions returned on the FP stack //
|
||||
////////////////////////////////////////////////
|
||||
Tile *Codegen_x86::munchFPUnary( TNode *t ){
|
||||
Tile* Codegen_x86::munchFPUnary(TNode* t)
|
||||
{
|
||||
string s;
|
||||
switch( t->op ){
|
||||
case IR_FNEG:s="\tfchs\n";break;
|
||||
default:return 0;
|
||||
switch (t->op) {
|
||||
case IR_FNEG:
|
||||
s = "\tfchs\n";
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return new Tile( s,munchFP( t->l ) );
|
||||
return new Tile(s, munchFP(t->l));
|
||||
}
|
||||
|
||||
Tile *Codegen_x86::munchFPArith( TNode *t ){
|
||||
string s,s2;
|
||||
switch( t->op ){
|
||||
case IR_FADD:s="\tfaddp\tst(1)\n";break;
|
||||
case IR_FMUL:s="\tfmulp\tst(1)\n";break;
|
||||
case IR_FSUB:s="\tfsubrp\tst(1)\n";s2="\tfsubp\tst(1)\n";break;
|
||||
case IR_FDIV:s="\tfdivrp\tst(1)\n";s2="\tfdivp\tst(1)\n";break;
|
||||
default:return 0;
|
||||
Tile* Codegen_x86::munchFPArith(TNode* t)
|
||||
{
|
||||
string s, s2;
|
||||
switch (t->op) {
|
||||
case IR_FADD:
|
||||
s = "\tfaddp\tst(1)\n";
|
||||
break;
|
||||
case IR_FMUL:
|
||||
s = "\tfmulp\tst(1)\n";
|
||||
break;
|
||||
case IR_FSUB:
|
||||
s = "\tfsubrp\tst(1)\n";
|
||||
s2 = "\tfsubp\tst(1)\n";
|
||||
break;
|
||||
case IR_FDIV:
|
||||
s = "\tfdivrp\tst(1)\n";
|
||||
s2 = "\tfdivp\tst(1)\n";
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return new Tile( s,s2,munchFP( t->l ),munchFP( t->r ) );
|
||||
return new Tile(s, s2, munchFP(t->l), munchFP(t->r));
|
||||
}
|
||||
|
||||
Tile *Codegen_x86::munchFPRelop( TNode *t ){
|
||||
string s,s2;
|
||||
switch( t->op ){
|
||||
case IR_FSETEQ:s="z";s2="z";break;
|
||||
case IR_FSETNE:s="nz";s2="nz";break;
|
||||
case IR_FSETLT:s="b";s2="a";break;
|
||||
case IR_FSETGT:s="a";s2="b";break;
|
||||
case IR_FSETLE:s="be";s2="ae";break;
|
||||
case IR_FSETGE:s="ae";s2="be";break;
|
||||
default:return 0;
|
||||
Tile* Codegen_x86::munchFPRelop(TNode* t)
|
||||
{
|
||||
string s, s2;
|
||||
switch (t->op) {
|
||||
case IR_FSETEQ:
|
||||
s = "z";
|
||||
s2 = "z";
|
||||
break;
|
||||
case IR_FSETNE:
|
||||
s = "nz";
|
||||
s2 = "nz";
|
||||
break;
|
||||
case IR_FSETLT:
|
||||
s = "b";
|
||||
s2 = "a";
|
||||
break;
|
||||
case IR_FSETGT:
|
||||
s = "a";
|
||||
s2 = "b";
|
||||
break;
|
||||
case IR_FSETLE:
|
||||
s = "be";
|
||||
s2 = "ae";
|
||||
break;
|
||||
case IR_FSETGE:
|
||||
s = "ae";
|
||||
s2 = "be";
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
s="\tfucompp\n\tfnstsw\tax\n\tsahf\n\tset"+s+"\tal\n\tmovzx\t%l,al\n";
|
||||
s2="\tfucompp\n\tfnstsw\tax\n\tsahf\n\tset"+s2+"\tal\n\tmovzx\t%l,al\n";
|
||||
Tile *q=new Tile( s,s2,munchFP( t->l ),munchFP( t->r ) );
|
||||
q->want_l=EAX;
|
||||
s = "\tfucompp\n\tfnstsw\tax\n\tsahf\n\tset" + s + "\tal\n\tmovzx\t%l,al\n";
|
||||
s2 = "\tfucompp\n\tfnstsw\tax\n\tsahf\n\tset" + s2 + "\tal\n\tmovzx\t%l,al\n";
|
||||
Tile* q = new Tile(s, s2, munchFP(t->l), munchFP(t->r));
|
||||
q->want_l = EAX;
|
||||
return q;
|
||||
}
|
||||
|
||||
///////////////////////////
|
||||
// Generic Call handling //
|
||||
///////////////////////////
|
||||
Tile *Codegen_x86::munchCall( TNode *t ){
|
||||
Tile *q;
|
||||
if( t->l->op==IR_GLOBAL ){
|
||||
q=new Tile( "\tcall\t"+t->l->sconst+"\n",t->r ? munchReg( t->r ) : 0 );
|
||||
}else{
|
||||
q=new Tile( "\tcall\t%l\n",munchReg( t->l ),t->r ? munchReg( t->r ) : 0 );
|
||||
Tile* Codegen_x86::munchCall(TNode* t)
|
||||
{
|
||||
Tile* q;
|
||||
if (t->l->op == IR_GLOBAL) {
|
||||
q = new Tile("\tcall\t" + t->l->sconst + "\n", t->r ? munchReg(t->r) : 0);
|
||||
} else {
|
||||
q = new Tile("\tcall\t%l\n", munchReg(t->l), t->r ? munchReg(t->r) : 0);
|
||||
}
|
||||
q->argFrame=t->iconst;
|
||||
q->want_l=EAX;
|
||||
q->hits=(1<<EAX)|(1<<ECX)|(1<<EDX);
|
||||
q->argFrame = t->iconst;
|
||||
q->want_l = EAX;
|
||||
q->hits = (1 << EAX) | (1 << ECX) | (1 << EDX);
|
||||
return q;
|
||||
}
|
||||
|
||||
/////////////////////////////
|
||||
// munch and dicard result //
|
||||
/////////////////////////////
|
||||
Tile *Codegen_x86::munch( TNode *t ){
|
||||
if( !t ) return 0;
|
||||
Tile *q=0;
|
||||
Tile* Codegen_x86::munch(TNode* t)
|
||||
{
|
||||
if (!t)
|
||||
return 0;
|
||||
Tile* q = 0;
|
||||
string s;
|
||||
switch( t->op ){
|
||||
switch (t->op) {
|
||||
case IR_JSR:
|
||||
q=new Tile( "\tcall\t"+t->sconst+'\n' );
|
||||
q = new Tile("\tcall\t" + t->sconst + '\n');
|
||||
break;
|
||||
case IR_RET:
|
||||
q=new Tile( "\tret\n" );
|
||||
q = new Tile("\tret\n");
|
||||
break;
|
||||
case IR_RETURN:
|
||||
q=munchReg( t->l );q->want_l=EAX;
|
||||
s="\tjmp\t"+t->sconst+'\n';
|
||||
q=new Tile( s,q );
|
||||
q = munchReg(t->l);
|
||||
q->want_l = EAX;
|
||||
s = "\tjmp\t" + t->sconst + '\n';
|
||||
q = new Tile(s, q);
|
||||
break;
|
||||
case IR_FRETURN:
|
||||
q=munchFP( t->l );
|
||||
s="\tjmp\t"+t->sconst+'\n';
|
||||
q=new Tile( s,q );
|
||||
q = munchFP(t->l);
|
||||
s = "\tjmp\t" + t->sconst + '\n';
|
||||
q = new Tile(s, q);
|
||||
break;
|
||||
case IR_CALL:
|
||||
q=munchCall( t );
|
||||
q = munchCall(t);
|
||||
break;
|
||||
case IR_JUMP:
|
||||
q=new Tile( "\tjmp\t"+t->sconst+'\n' );
|
||||
q = new Tile("\tjmp\t" + t->sconst + '\n');
|
||||
break;
|
||||
case IR_JUMPT:
|
||||
if( TNode *p=t->l ){
|
||||
bool neg=false;
|
||||
if( isRelop( p->op ) ){
|
||||
if (TNode* p = t->l) {
|
||||
bool neg = false;
|
||||
if (isRelop(p->op)) {
|
||||
string func;
|
||||
q=genCompare( p,func,neg );
|
||||
q=new Tile( "\tj"+func+"\t"+t->sconst+"\n",q );
|
||||
q = genCompare(p, func, neg);
|
||||
q = new Tile("\tj" + func + "\t" + t->sconst + "\n", q);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case IR_JUMPF:
|
||||
if( TNode *p=t->l ){
|
||||
bool neg=true;
|
||||
if( isRelop( p->op ) ){
|
||||
if (TNode* p = t->l) {
|
||||
bool neg = true;
|
||||
if (isRelop(p->op)) {
|
||||
string func;
|
||||
q=genCompare( p,func,neg );
|
||||
q=new Tile( "\tj"+func+"\t"+t->sconst+"\n",q );
|
||||
q = genCompare(p, func, neg);
|
||||
q = new Tile("\tj" + func + "\t" + t->sconst + "\n", q);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case IR_MOVE:
|
||||
if( matchMEM( t->r,s ) ){
|
||||
if (matchMEM(t->r, s)) {
|
||||
string c;
|
||||
if( matchCONST( t->l,c ) ){
|
||||
q=new Tile( "\tmov\t"+s+","+c+"\n" );
|
||||
}else if( t->l->op==IR_ADD || t->l->op==IR_SUB ){
|
||||
TNode *p=0;
|
||||
if( nodesEqual( t->l->l,t->r ) ) p=t->l->r;
|
||||
else if( t->l->op==IR_ADD && nodesEqual( t->l->r,t->r ) ) p=t->l->l;
|
||||
if( p ){
|
||||
string c,op;
|
||||
switch( t->l->op ){
|
||||
case IR_ADD:op="\tadd\t";break;
|
||||
case IR_SUB:op="\tsub\t";break;
|
||||
if (matchCONST(t->l, c)) {
|
||||
q = new Tile("\tmov\t" + s + "," + c + "\n");
|
||||
} else if (t->l->op == IR_ADD || t->l->op == IR_SUB) {
|
||||
TNode* p = 0;
|
||||
if (nodesEqual(t->l->l, t->r))
|
||||
p = t->l->r;
|
||||
else if (t->l->op == IR_ADD && nodesEqual(t->l->r, t->r))
|
||||
p = t->l->l;
|
||||
if (p) {
|
||||
string c, op;
|
||||
switch (t->l->op) {
|
||||
case IR_ADD:
|
||||
op = "\tadd\t";
|
||||
break;
|
||||
case IR_SUB:
|
||||
op = "\tsub\t";
|
||||
break;
|
||||
}
|
||||
if( matchCONST( p,c ) ){
|
||||
q=new Tile( op+s+","+c+"\n" );
|
||||
}else{
|
||||
q=new Tile( op+s+",%l\n",munchReg( p ) );
|
||||
if (matchCONST(p, c)) {
|
||||
q = new Tile(op + s + "," + c + "\n");
|
||||
} else {
|
||||
q = new Tile(op + s + ",%l\n", munchReg(p));
|
||||
}
|
||||
}
|
||||
}
|
||||
if( !q ) q=new Tile( "\tmov\t"+s+",%l\n",munchReg( t->l ) );
|
||||
if (!q)
|
||||
q = new Tile("\tmov\t" + s + ",%l\n", munchReg(t->l));
|
||||
}
|
||||
break;
|
||||
}
|
||||
if( !q ) q=munchReg( t );
|
||||
if (!q)
|
||||
q = munchReg(t);
|
||||
return q;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////
|
||||
// munch and return result in a register //
|
||||
///////////////////////////////////////////
|
||||
Tile *Codegen_x86::munchReg( TNode *t ){
|
||||
if( !t ) return 0;
|
||||
Tile* Codegen_x86::munchReg(TNode* t)
|
||||
{
|
||||
if (!t)
|
||||
return 0;
|
||||
|
||||
string s;
|
||||
Tile *q=0;
|
||||
Tile* q = 0;
|
||||
|
||||
switch( t->op ){
|
||||
switch (t->op) {
|
||||
case IR_JUMPT:
|
||||
q=new Tile( "\tand\t%l,%l\n\tjnz\t"+t->sconst+'\n',munchReg( t->l ) );
|
||||
q = new Tile("\tand\t%l,%l\n\tjnz\t" + t->sconst + '\n', munchReg(t->l));
|
||||
break;
|
||||
case IR_JUMPF:
|
||||
q=new Tile( "\tand\t%l,%l\n\tjz\t"+t->sconst+'\n',munchReg( t->l ) );
|
||||
q = new Tile("\tand\t%l,%l\n\tjz\t" + t->sconst + '\n', munchReg(t->l));
|
||||
break;
|
||||
case IR_JUMPGE:
|
||||
q=new Tile( "\tcmp\t%l,%r\n\tjnc\t"+t->sconst+'\n',munchReg( t->l ),munchReg( t->r ) );
|
||||
q = new Tile("\tcmp\t%l,%r\n\tjnc\t" + t->sconst + '\n', munchReg(t->l), munchReg(t->r));
|
||||
break;
|
||||
case IR_CALL:
|
||||
q=munchCall( t );
|
||||
q = munchCall(t);
|
||||
break;
|
||||
case IR_MOVE:
|
||||
//MUST BE MOVE TO MEM!
|
||||
if( matchMEM( t->r,s ) ){
|
||||
q=new Tile( "\tmov\t"+s+",%l\n",munchReg( t->l ) );
|
||||
}else if( t->r->op==IR_MEM ){
|
||||
q=new Tile( "\tmov\t[%r],%l\n",munchReg( t->l ),munchReg( t->r->l ) );
|
||||
if (matchMEM(t->r, s)) {
|
||||
q = new Tile("\tmov\t" + s + ",%l\n", munchReg(t->l));
|
||||
} else if (t->r->op == IR_MEM) {
|
||||
q = new Tile("\tmov\t[%r],%l\n", munchReg(t->l), munchReg(t->r->l));
|
||||
}
|
||||
break;
|
||||
case IR_MEM:
|
||||
if( matchMEM( t,s ) ){
|
||||
q=new Tile( "\tmov\t%l,"+s+"\n" );
|
||||
}else{
|
||||
q=new Tile( "\tmov\t%l,[%l]\n",munchReg( t->l ) );
|
||||
if (matchMEM(t, s)) {
|
||||
q = new Tile("\tmov\t%l," + s + "\n");
|
||||
} else {
|
||||
q = new Tile("\tmov\t%l,[%l]\n", munchReg(t->l));
|
||||
}
|
||||
break;
|
||||
case IR_SEQ:
|
||||
q=new Tile( "",munch(t->l),munch(t->r) );
|
||||
q = new Tile("", munch(t->l), munch(t->r));
|
||||
break;
|
||||
case IR_ARG:
|
||||
q=new Tile( "\tlea\t%l,[esp"+itoa_sgn(t->iconst)+"]\n" );
|
||||
q = new Tile("\tlea\t%l,[esp" + itoa_sgn(t->iconst) + "]\n");
|
||||
break;
|
||||
case IR_LOCAL:
|
||||
q=new Tile( "\tlea\t%l,[ebp"+itoa_sgn(t->iconst)+"]\n" );
|
||||
q = new Tile("\tlea\t%l,[ebp" + itoa_sgn(t->iconst) + "]\n");
|
||||
break;
|
||||
case IR_GLOBAL:
|
||||
q=new Tile( string( "\tmov\t%l," )+t->sconst+'\n' );
|
||||
q = new Tile(string("\tmov\t%l,") + t->sconst + '\n');
|
||||
break;
|
||||
case IR_CAST:
|
||||
q=munchFP( t->l );
|
||||
s="\tpush\t%l\n\tfistp\t[esp]\n\tpop\t%l\n";
|
||||
q=new Tile( s,q );
|
||||
q = munchFP(t->l);
|
||||
s = "\tpush\t%l\n\tfistp\t[esp]\n\tpop\t%l\n";
|
||||
q = new Tile(s, q);
|
||||
break;
|
||||
case IR_CONST:
|
||||
q=new Tile( "\tmov\t%l,"+itoa(t->iconst)+"\n" );
|
||||
q = new Tile("\tmov\t%l," + itoa(t->iconst) + "\n");
|
||||
break;
|
||||
case IR_NEG:
|
||||
q=munchUnary( t );
|
||||
q = munchUnary(t);
|
||||
break;
|
||||
case IR_AND:case IR_OR:case IR_XOR:
|
||||
q=munchLogical( t );
|
||||
case IR_AND:
|
||||
case IR_OR:
|
||||
case IR_XOR:
|
||||
q = munchLogical(t);
|
||||
break;
|
||||
case IR_ADD:case IR_SUB:case IR_MUL:case IR_DIV:
|
||||
q=munchArith( t );
|
||||
case IR_ADD:
|
||||
case IR_SUB:
|
||||
case IR_MUL:
|
||||
case IR_DIV:
|
||||
q = munchArith(t);
|
||||
break;
|
||||
case IR_SHL:case IR_SHR:case IR_SAR:
|
||||
q=munchShift( t );
|
||||
case IR_SHL:
|
||||
case IR_SHR:
|
||||
case IR_SAR:
|
||||
q = munchShift(t);
|
||||
break;
|
||||
case IR_SETEQ:case IR_SETNE:case IR_SETLT:case IR_SETGT:case IR_SETLE:case IR_SETGE:
|
||||
q=munchRelop( t );
|
||||
case IR_SETEQ:
|
||||
case IR_SETNE:
|
||||
case IR_SETLT:
|
||||
case IR_SETGT:
|
||||
case IR_SETLE:
|
||||
case IR_SETGE:
|
||||
q = munchRelop(t);
|
||||
break;
|
||||
case IR_FSETEQ:case IR_FSETNE:case IR_FSETLT:case IR_FSETGT:case IR_FSETLE:case IR_FSETGE:
|
||||
q=munchFPRelop( t );
|
||||
case IR_FSETEQ:
|
||||
case IR_FSETNE:
|
||||
case IR_FSETLT:
|
||||
case IR_FSETGT:
|
||||
case IR_FSETLE:
|
||||
case IR_FSETGE:
|
||||
q = munchFPRelop(t);
|
||||
break;
|
||||
default:
|
||||
q=munchFP( t );if( !q ) return 0;
|
||||
s="\tpush\t%l\n\tfstp\t[esp]\n\tpop\t%l\n";
|
||||
q=new Tile( s,q );
|
||||
q = munchFP(t);
|
||||
if (!q)
|
||||
return 0;
|
||||
s = "\tpush\t%l\n\tfstp\t[esp]\n\tpop\t%l\n";
|
||||
q = new Tile(s, q);
|
||||
}
|
||||
return q;
|
||||
}
|
||||
@@ -427,30 +565,37 @@ Tile *Codegen_x86::munchReg( TNode *t ){
|
||||
/////////////////////////////////////////
|
||||
// munch and return result on FP stack //
|
||||
/////////////////////////////////////////
|
||||
Tile *Codegen_x86::munchFP( TNode *t ){
|
||||
if( !t ) return 0;
|
||||
Tile* Codegen_x86::munchFP(TNode* t)
|
||||
{
|
||||
if (!t)
|
||||
return 0;
|
||||
|
||||
string s;
|
||||
Tile *q=0;
|
||||
Tile* q = 0;
|
||||
|
||||
switch( t->op ){
|
||||
switch (t->op) {
|
||||
case IR_FCALL:
|
||||
q=munchCall( t );
|
||||
q = munchCall(t);
|
||||
break;
|
||||
case IR_FCAST:
|
||||
s="\tpush\t%l\n\tfild\t[esp]\n\tpop\t%l\n";
|
||||
q=new Tile( s,munchReg( t->l ) );
|
||||
s = "\tpush\t%l\n\tfild\t[esp]\n\tpop\t%l\n";
|
||||
q = new Tile(s, munchReg(t->l));
|
||||
break;
|
||||
case IR_FNEG:
|
||||
q=munchFPUnary( t );
|
||||
q = munchFPUnary(t);
|
||||
break;
|
||||
case IR_FADD:case IR_FSUB:case IR_FMUL:case IR_FDIV:
|
||||
q=munchFPArith( t );
|
||||
case IR_FADD:
|
||||
case IR_FSUB:
|
||||
case IR_FMUL:
|
||||
case IR_FDIV:
|
||||
q = munchFPArith(t);
|
||||
break;
|
||||
default:
|
||||
q=munchReg( t );if( !q ) return 0;
|
||||
s="\tpush\t%l\n\tfld\t[esp]\n\tpop\t%l\n";
|
||||
q=new Tile( s,q );
|
||||
q = munchReg(t);
|
||||
if (!q)
|
||||
return 0;
|
||||
s = "\tpush\t%l\n\tfld\t[esp]\n\tpop\t%l\n";
|
||||
q = new Tile(s, q);
|
||||
}
|
||||
return q;
|
||||
}
|
||||
|
||||
+150
-83
@@ -1,13 +1,12 @@
|
||||
|
||||
#include "tile.h"
|
||||
#include "../std.h"
|
||||
#include "codegen_x86.h"
|
||||
#include "tile.h"
|
||||
|
||||
//reduce to 3 for stress test
|
||||
static const int NUM_REGS = 6;
|
||||
|
||||
static const string regs[] =
|
||||
{ "???","eax","ecx","edx","edi","esi","ebx" };
|
||||
static const string regs[] = {"???", "eax", "ecx", "edx", "edi", "esi", "ebx"};
|
||||
|
||||
//array of 'used' flags
|
||||
static bool regUsed[NUM_REGS + 1];
|
||||
@@ -21,85 +20,117 @@ static vector<string> codeFrags, dataFrags;
|
||||
//name of function
|
||||
static string funcLabel;
|
||||
|
||||
static void resetRegs() {
|
||||
for (int n = 1; n <= NUM_REGS; ++n) regUsed[n] = false;
|
||||
static void resetRegs()
|
||||
{
|
||||
for (int n = 1; n <= NUM_REGS; ++n)
|
||||
regUsed[n] = false;
|
||||
}
|
||||
|
||||
static int allocReg(int n) {
|
||||
static int allocReg(int n)
|
||||
{
|
||||
if (!n || regUsed[n]) {
|
||||
for (n = NUM_REGS; n >= 1 && regUsed[n]; --n) {}
|
||||
if (!n) return 0;
|
||||
for (n = NUM_REGS; n >= 1 && regUsed[n]; --n) {
|
||||
}
|
||||
if (!n)
|
||||
return 0;
|
||||
}
|
||||
regUsed[n] = true;
|
||||
return n;
|
||||
}
|
||||
|
||||
static void freeReg(int n) {
|
||||
static void freeReg(int n)
|
||||
{
|
||||
regUsed[n] = false;
|
||||
}
|
||||
|
||||
static void pushReg(int n) {
|
||||
static void pushReg(int n)
|
||||
{
|
||||
frameSize += 4;
|
||||
if (frameSize > maxFrameSize) maxFrameSize = frameSize;
|
||||
if (frameSize > maxFrameSize)
|
||||
maxFrameSize = frameSize;
|
||||
char buff[32];
|
||||
_itoa(frameSize, buff, 10);
|
||||
string s = "\tmov\t[ebp-"; s += buff; s += "],"; s += regs[n]; s += '\n';
|
||||
string s = "\tmov\t[ebp-";
|
||||
s += buff;
|
||||
s += "],";
|
||||
s += regs[n];
|
||||
s += '\n';
|
||||
codeFrags.push_back(s);
|
||||
}
|
||||
|
||||
static void popReg(int n) {
|
||||
char buff[32]; _itoa(frameSize, buff, 10);
|
||||
string s = "\tmov\t"; s += regs[n]; s += ",[ebp-"; s += buff; s += "]\n";
|
||||
static void popReg(int n)
|
||||
{
|
||||
char buff[32];
|
||||
_itoa(frameSize, buff, 10);
|
||||
string s = "\tmov\t";
|
||||
s += regs[n];
|
||||
s += ",[ebp-";
|
||||
s += buff;
|
||||
s += "]\n";
|
||||
codeFrags.push_back(s);
|
||||
frameSize -= 4;
|
||||
}
|
||||
|
||||
static void moveReg(int d, int s) {
|
||||
static void moveReg(int d, int s)
|
||||
{
|
||||
string t = "\tmov\t" + regs[d] + ',' + regs[s] + '\n';
|
||||
codeFrags.push_back(t);
|
||||
}
|
||||
|
||||
static void swapRegs(int d, int s) {
|
||||
static void swapRegs(int d, int s)
|
||||
{
|
||||
string t = "\txchg\t" + regs[d] + ',' + regs[s] + '\n';
|
||||
codeFrags.push_back(t);
|
||||
}
|
||||
|
||||
Tile::Tile(const string &a, Tile *l, Tile *r)
|
||||
:assem(a), l(l), r(r), want_l(0), want_r(0), hits(0), need(0), argFrame(0) {
|
||||
Tile::Tile(const string& a, Tile* l, Tile* r)
|
||||
: assem(a), l(l), r(r), want_l(0), want_r(0), hits(0), need(0), argFrame(0)
|
||||
{}
|
||||
|
||||
Tile::Tile(const string& a, const string& a2, Tile* l, Tile* r)
|
||||
: assem(a), assem2(a2), l(l), r(r), want_l(0), want_r(0), hits(0), need(0), argFrame(0)
|
||||
{}
|
||||
|
||||
Tile::~Tile()
|
||||
{
|
||||
delete l;
|
||||
delete r;
|
||||
}
|
||||
|
||||
Tile::Tile(const string &a, const string &a2, Tile *l, Tile *r)
|
||||
: assem(a), assem2(a2), l(l), r(r), want_l(0), want_r(0), hits(0), need(0), argFrame(0) {
|
||||
}
|
||||
|
||||
Tile::~Tile() {
|
||||
delete l; delete r;
|
||||
}
|
||||
|
||||
void Tile::label() {
|
||||
void Tile::label()
|
||||
{
|
||||
if (!l) {
|
||||
need = 1;
|
||||
} else if (!r) {
|
||||
l->label();
|
||||
need = l->need;
|
||||
} else {
|
||||
l->label(); r->label();
|
||||
if (l->need == r->need) need = l->need + 1;
|
||||
else if (l->need > r->need) need = l->need;
|
||||
else need = r->need;
|
||||
l->label();
|
||||
r->label();
|
||||
if (l->need == r->need)
|
||||
need = l->need + 1;
|
||||
else if (l->need > r->need)
|
||||
need = l->need;
|
||||
else
|
||||
need = r->need;
|
||||
}
|
||||
}
|
||||
|
||||
int Tile::eval(int want) {
|
||||
int Tile::eval(int want)
|
||||
{
|
||||
//save any hit registers
|
||||
int spill = hits;
|
||||
if (want_l) spill |= 1 << want_l;
|
||||
if (want_r) spill |= 1 << want_r;
|
||||
if (want_l)
|
||||
spill |= 1 << want_l;
|
||||
if (want_r)
|
||||
spill |= 1 << want_r;
|
||||
if (spill) {
|
||||
for (int n = 1; n <= NUM_REGS; ++n) {
|
||||
if (spill&(1 << n)) {
|
||||
if (regUsed[n]) pushReg(n);
|
||||
else spill &= ~(1 << n);
|
||||
if (spill & (1 << n)) {
|
||||
if (regUsed[n])
|
||||
pushReg(n);
|
||||
else
|
||||
spill &= ~(1 << n);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -110,9 +141,10 @@ int Tile::eval(int want) {
|
||||
}
|
||||
|
||||
int got_l = 0, got_r = 0;
|
||||
if (want_l) want = want_l;
|
||||
if (want_l)
|
||||
want = want_l;
|
||||
|
||||
string *as = &assem;
|
||||
string* as = &assem;
|
||||
|
||||
if (!l) {
|
||||
got_l = allocReg(want);
|
||||
@@ -121,85 +153,105 @@ int Tile::eval(int want) {
|
||||
} else {
|
||||
if (l->need >= NUM_REGS && r->need >= NUM_REGS) {
|
||||
got_r = r->eval(0);
|
||||
pushReg(got_r); freeReg(got_r);
|
||||
pushReg(got_r);
|
||||
freeReg(got_r);
|
||||
got_l = l->eval(want);
|
||||
got_r = allocReg(want_r); popReg(got_r);
|
||||
got_r = allocReg(want_r);
|
||||
popReg(got_r);
|
||||
} else if (r->need > l->need) {
|
||||
got_r = r->eval(want_r);
|
||||
got_l = l->eval(want);
|
||||
} else {
|
||||
got_l = l->eval(want);
|
||||
got_r = r->eval(want_r);
|
||||
if (assem2.size()) as = &assem2;
|
||||
if (assem2.size())
|
||||
as = &assem2;
|
||||
}
|
||||
if (want_l == got_r || want_r == got_l) {
|
||||
swapRegs(got_l, got_r);
|
||||
int t = got_l; got_l = got_r; got_r = t;
|
||||
int t = got_l;
|
||||
got_l = got_r;
|
||||
got_r = t;
|
||||
}
|
||||
}
|
||||
|
||||
if (!want_l) want_l = got_l;
|
||||
else if (want_l != got_l) moveReg(want_l, got_l);
|
||||
if (!want_l)
|
||||
want_l = got_l;
|
||||
else if (want_l != got_l)
|
||||
moveReg(want_l, got_l);
|
||||
|
||||
if (!want_r) want_r = got_r;
|
||||
else if (want_r != got_r) moveReg(want_r, got_r);
|
||||
if (!want_r)
|
||||
want_r = got_r;
|
||||
else if (want_r != got_r)
|
||||
moveReg(want_r, got_r);
|
||||
|
||||
int i;
|
||||
while ((i = as->find("%l")) != string::npos) as->replace(i, 2, regs[want_l]);
|
||||
while ((i = as->find("%r")) != string::npos) as->replace(i, 2, regs[want_r]);
|
||||
while ((i = as->find("%l")) != string::npos)
|
||||
as->replace(i, 2, regs[want_l]);
|
||||
while ((i = as->find("%r")) != string::npos)
|
||||
as->replace(i, 2, regs[want_r]);
|
||||
|
||||
codeFrags.push_back(*as);
|
||||
|
||||
freeReg(got_r);
|
||||
if (want_l != got_l) moveReg(got_l, want_l);
|
||||
if (want_l != got_l)
|
||||
moveReg(got_l, want_l);
|
||||
|
||||
//cleanup argFrame
|
||||
if (argFrame) {
|
||||
//***** Not needed for STDCALL *****
|
||||
// codeFrags.push_back( "+"+itoa(argFrame) );
|
||||
// codeFrags.push_back( "+"+itoa(argFrame) );
|
||||
}
|
||||
|
||||
//restore spilled regs
|
||||
if (spill) {
|
||||
for (int n = NUM_REGS; n >= 1; --n) {
|
||||
if (spill&(1 << n)) popReg(n);
|
||||
if (spill & (1 << n))
|
||||
popReg(n);
|
||||
}
|
||||
}
|
||||
return got_l;
|
||||
}
|
||||
|
||||
void Codegen_x86::flush() {
|
||||
void Codegen_x86::flush()
|
||||
{
|
||||
vector<string>::iterator it;
|
||||
for (it = dataFrags.begin(); it != dataFrags.end(); ++it) out << *it;
|
||||
for (it = dataFrags.begin(); it != dataFrags.end(); ++it)
|
||||
out << *it;
|
||||
dataFrags.clear();
|
||||
}
|
||||
|
||||
void Codegen_x86::enter(const string &l, int frameSize) {
|
||||
|
||||
inCode = true;
|
||||
void Codegen_x86::enter(const string& l, int frameSize)
|
||||
{
|
||||
inCode = true;
|
||||
::frameSize = maxFrameSize = frameSize;
|
||||
codeFrags.clear(); funcLabel = l;
|
||||
codeFrags.clear();
|
||||
funcLabel = l;
|
||||
}
|
||||
|
||||
void Codegen_x86::code(TNode *stmt) {
|
||||
void Codegen_x86::code(TNode* stmt)
|
||||
{
|
||||
resetRegs();
|
||||
Tile *q = munch(stmt);
|
||||
Tile* q = munch(stmt);
|
||||
q->label();
|
||||
q->eval(0);
|
||||
delete q;
|
||||
delete stmt;
|
||||
}
|
||||
|
||||
static string fixEsp(int esp_off) {
|
||||
if (esp_off < 0) return "\tsub\tesp," + itoa(-esp_off) + "\n";
|
||||
static string fixEsp(int esp_off)
|
||||
{
|
||||
if (esp_off < 0)
|
||||
return "\tsub\tesp," + itoa(-esp_off) + "\n";
|
||||
return "\tadd\tesp," + itoa(esp_off) + "\n";
|
||||
}
|
||||
|
||||
void Codegen_x86::leave(TNode *cleanup, int pop_sz) {
|
||||
void Codegen_x86::leave(TNode* cleanup, int pop_sz)
|
||||
{
|
||||
if (cleanup) {
|
||||
resetRegs();
|
||||
allocReg(EAX);
|
||||
Tile *q = munch(cleanup);
|
||||
Tile* q = munch(cleanup);
|
||||
q->label();
|
||||
q->eval(0);
|
||||
delete q;
|
||||
@@ -207,19 +259,21 @@ void Codegen_x86::leave(TNode *cleanup, int pop_sz) {
|
||||
|
||||
out << "\t.align\t16\n";
|
||||
|
||||
if (funcLabel.size()) out << funcLabel << '\n';
|
||||
if (funcLabel.size())
|
||||
out << funcLabel << '\n';
|
||||
|
||||
out << "\tpush\tebx\n";
|
||||
out << "\tpush\tesi\n";
|
||||
out << "\tpush\tedi\n";
|
||||
out << "\tpush\tebp\n";
|
||||
out << "\tmov\tebp,esp\n";
|
||||
if (maxFrameSize) out << "\tsub\tesp," << maxFrameSize << '\n';
|
||||
if (maxFrameSize)
|
||||
out << "\tsub\tesp," << maxFrameSize << '\n';
|
||||
|
||||
int esp_off = 0;
|
||||
vector<string>::iterator it = codeFrags.begin();
|
||||
int esp_off = 0;
|
||||
vector<string>::iterator it = codeFrags.begin();
|
||||
for (it = codeFrags.begin(); it != codeFrags.end(); ++it) {
|
||||
const string &t = *it;
|
||||
const string& t = *it;
|
||||
if (t[0] == '+') {
|
||||
esp_off += atoi(t.substr(1));
|
||||
} else if (t[0] == '-') {
|
||||
@@ -233,7 +287,8 @@ void Codegen_x86::leave(TNode *cleanup, int pop_sz) {
|
||||
out << *it;
|
||||
}
|
||||
}
|
||||
if (esp_off) out << fixEsp(esp_off);
|
||||
if (esp_off)
|
||||
out << fixEsp(esp_off);
|
||||
|
||||
out << "\tmov\tesp,ebp\n";
|
||||
out << "\tpop\tebp\n";
|
||||
@@ -246,29 +301,41 @@ void Codegen_x86::leave(TNode *cleanup, int pop_sz) {
|
||||
inCode = false;
|
||||
}
|
||||
|
||||
void Codegen_x86::label(const string &l) {
|
||||
void Codegen_x86::label(const string& l)
|
||||
{
|
||||
string t = l + '\n';
|
||||
if (inCode) codeFrags.push_back(t);
|
||||
else dataFrags.push_back(t);
|
||||
if (inCode)
|
||||
codeFrags.push_back(t);
|
||||
else
|
||||
dataFrags.push_back(t);
|
||||
}
|
||||
|
||||
void Codegen_x86::align_data(int n) {
|
||||
char buff[32]; _itoa(n, buff, 10);
|
||||
void Codegen_x86::align_data(int n)
|
||||
{
|
||||
char buff[32];
|
||||
_itoa(n, buff, 10);
|
||||
dataFrags.push_back(string("\t.align\t") + buff + '\n');
|
||||
}
|
||||
|
||||
void Codegen_x86::i_data(int i, const string &l) {
|
||||
if (l.size()) dataFrags.push_back(l);
|
||||
char buff[32]; _itoa(i, buff, 10);
|
||||
void Codegen_x86::i_data(int i, const string& l)
|
||||
{
|
||||
if (l.size())
|
||||
dataFrags.push_back(l);
|
||||
char buff[32];
|
||||
_itoa(i, buff, 10);
|
||||
dataFrags.push_back(string("\t.dd\t") + buff + '\n');
|
||||
}
|
||||
|
||||
void Codegen_x86::s_data(const string &s, const string &l) {
|
||||
if (l.size()) dataFrags.push_back(l);
|
||||
void Codegen_x86::s_data(const string& s, const string& l)
|
||||
{
|
||||
if (l.size())
|
||||
dataFrags.push_back(l);
|
||||
dataFrags.push_back(string("\t.db\t\"") + s + "\",0\n");
|
||||
}
|
||||
|
||||
void Codegen_x86::p_data(const string &p, const string &l) {
|
||||
if (l.size()) dataFrags.push_back(l);
|
||||
void Codegen_x86::p_data(const string& p, const string& l)
|
||||
{
|
||||
if (l.size())
|
||||
dataFrags.push_back(l);
|
||||
dataFrags.push_back(string("\t.dd\t") + p + '\n');
|
||||
}
|
||||
|
||||
+24
-20
@@ -1,35 +1,39 @@
|
||||
|
||||
#include "std.hpp"
|
||||
#include "decl.hpp"
|
||||
#include "std.hpp"
|
||||
#include "type.hpp"
|
||||
|
||||
Decl::~Decl(){
|
||||
Decl::~Decl() {}
|
||||
|
||||
DeclSeq::DeclSeq() {}
|
||||
|
||||
void Decl::getName(char* buff)
|
||||
{
|
||||
int sz = name.size();
|
||||
memcpy(buff, name.data(), sz);
|
||||
buff[sz] = 0;
|
||||
}
|
||||
|
||||
DeclSeq::DeclSeq(){
|
||||
DeclSeq::~DeclSeq()
|
||||
{
|
||||
for (; decls.size(); decls.pop_back())
|
||||
delete decls.back();
|
||||
}
|
||||
|
||||
void Decl::getName( char *buff ){
|
||||
int sz=name.size();
|
||||
memcpy( buff,name.data(),sz );
|
||||
buff[sz]=0;
|
||||
}
|
||||
|
||||
DeclSeq::~DeclSeq(){
|
||||
for( ;decls.size();decls.pop_back() ) delete decls.back();
|
||||
}
|
||||
|
||||
Decl *DeclSeq::findDecl( const string &s ){
|
||||
Decl* DeclSeq::findDecl(const string& s)
|
||||
{
|
||||
vector<Decl*>::iterator it;
|
||||
for( it=decls.begin();it!=decls.end();++it ){
|
||||
if( (*it)->name==s ) return *it;
|
||||
for (it = decls.begin(); it != decls.end(); ++it) {
|
||||
if ((*it)->name == s)
|
||||
return *it;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
Decl *DeclSeq::insertDecl( const string &s,Type *t,int kind,ConstType *d ){
|
||||
if( findDecl( s ) ) return 0;
|
||||
decls.push_back( new Decl( s,t,kind,d ) );
|
||||
Decl* DeclSeq::insertDecl(const string& s, Type* t, int kind, ConstType* d)
|
||||
{
|
||||
if (findDecl(s))
|
||||
return 0;
|
||||
decls.push_back(new Decl(s, t, kind, d));
|
||||
return decls.back();
|
||||
}
|
||||
|
||||
|
||||
+22
-14
@@ -2,32 +2,40 @@
|
||||
#ifndef DECL_H
|
||||
#define DECL_H
|
||||
|
||||
enum{
|
||||
DECL_FUNC=1,DECL_ARRAY=2,DECL_STRUCT=4, //NOT vars
|
||||
DECL_GLOBAL=8,DECL_LOCAL=16,DECL_PARAM=32,DECL_FIELD=64 //ARE vars
|
||||
enum {
|
||||
DECL_FUNC = 1,
|
||||
DECL_ARRAY = 2,
|
||||
DECL_STRUCT = 4, //NOT vars
|
||||
DECL_GLOBAL = 8,
|
||||
DECL_LOCAL = 16,
|
||||
DECL_PARAM = 32,
|
||||
DECL_FIELD = 64 //ARE vars
|
||||
};
|
||||
|
||||
struct Type;
|
||||
struct ConstType;
|
||||
|
||||
struct Decl{
|
||||
string name;
|
||||
Type *type; //type
|
||||
int kind,offset;
|
||||
ConstType *defType; //default value
|
||||
Decl( const string &s,Type *t,int k,ConstType *d=0 ):name(s),type(t),kind(k),defType(d){}
|
||||
struct Decl {
|
||||
string name;
|
||||
Type* type; //type
|
||||
int kind, offset;
|
||||
ConstType* defType; //default value
|
||||
Decl(const string& s, Type* t, int k, ConstType* d = 0) : name(s), type(t), kind(k), defType(d) {}
|
||||
~Decl();
|
||||
|
||||
virtual void getName( char *buff );
|
||||
virtual void getName(char* buff);
|
||||
};
|
||||
|
||||
struct DeclSeq{
|
||||
struct DeclSeq {
|
||||
vector<Decl*> decls;
|
||||
DeclSeq();
|
||||
~DeclSeq();
|
||||
Decl *findDecl( const string &s );
|
||||
Decl *insertDecl( const string &s,Type *t,int kind,ConstType *d=0 );
|
||||
int size(){ return decls.size(); }
|
||||
Decl* findDecl(const string& s);
|
||||
Decl* insertDecl(const string& s, Type* t, int kind, ConstType* d = 0);
|
||||
int size()
|
||||
{
|
||||
return decls.size();
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
+173
-104
@@ -1,45 +1,65 @@
|
||||
|
||||
#include "std.hpp"
|
||||
#include "nodes.hpp"
|
||||
#include "std.hpp"
|
||||
|
||||
//////////////////////////////
|
||||
// Sequence of declarations //
|
||||
//////////////////////////////
|
||||
void DeclSeqNode::proto(DeclSeq *d, Environ *e) {
|
||||
void DeclSeqNode::proto(DeclSeq* d, Environ* e)
|
||||
{
|
||||
for (size_t k = 0; k < decls.size(); ++k) {
|
||||
try { decls[k]->proto(d, e); } catch (Ex &x) {
|
||||
if (x.pos < 0) x.pos = decls[k]->pos;
|
||||
if (!x.file.size()) x.file = decls[k]->file;
|
||||
try {
|
||||
decls[k]->proto(d, e);
|
||||
} catch (Ex& x) {
|
||||
if (x.pos < 0)
|
||||
x.pos = decls[k]->pos;
|
||||
if (!x.file.size())
|
||||
x.file = decls[k]->file;
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DeclSeqNode::semant(Environ *e) {
|
||||
void DeclSeqNode::semant(Environ* e)
|
||||
{
|
||||
for (size_t k = 0; k < decls.size(); ++k) {
|
||||
try { decls[k]->semant(e); } catch (Ex &x) {
|
||||
if (x.pos < 0) x.pos = decls[k]->pos;
|
||||
if (!x.file.size()) x.file = decls[k]->file;
|
||||
try {
|
||||
decls[k]->semant(e);
|
||||
} catch (Ex& x) {
|
||||
if (x.pos < 0)
|
||||
x.pos = decls[k]->pos;
|
||||
if (!x.file.size())
|
||||
x.file = decls[k]->file;
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DeclSeqNode::translate(Codegen *g) {
|
||||
void DeclSeqNode::translate(Codegen* g)
|
||||
{
|
||||
for (size_t k = 0; k < decls.size(); ++k) {
|
||||
try { decls[k]->translate(g); } catch (Ex &x) {
|
||||
if (x.pos < 0) x.pos = decls[k]->pos;
|
||||
if (!x.file.size()) x.file = decls[k]->file;
|
||||
try {
|
||||
decls[k]->translate(g);
|
||||
} catch (Ex& x) {
|
||||
if (x.pos < 0)
|
||||
x.pos = decls[k]->pos;
|
||||
if (!x.file.size())
|
||||
x.file = decls[k]->file;
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DeclSeqNode::transdata(Codegen *g) {
|
||||
void DeclSeqNode::transdata(Codegen* g)
|
||||
{
|
||||
for (size_t k = 0; k < decls.size(); ++k) {
|
||||
try { decls[k]->transdata(g); } catch (Ex &x) {
|
||||
if (x.pos < 0) x.pos = decls[k]->pos;
|
||||
if (!x.file.size()) x.file = decls[k]->file;
|
||||
try {
|
||||
decls[k]->transdata(g);
|
||||
} catch (Ex& x) {
|
||||
if (x.pos < 0)
|
||||
x.pos = decls[k]->pos;
|
||||
if (!x.file.size())
|
||||
x.file = decls[k]->file;
|
||||
throw;
|
||||
}
|
||||
}
|
||||
@@ -48,11 +68,12 @@ void DeclSeqNode::transdata(Codegen *g) {
|
||||
////////////////////////////
|
||||
// Simple var declaration //
|
||||
////////////////////////////
|
||||
void VarDeclNode::proto(DeclSeq *d, Environ *e) {
|
||||
|
||||
Type *ty = tagType(tag, e);
|
||||
if (!ty) ty = Type::int_type;
|
||||
ConstType *defType = 0;
|
||||
void VarDeclNode::proto(DeclSeq* d, Environ* e)
|
||||
{
|
||||
Type* ty = tagType(tag, e);
|
||||
if (!ty)
|
||||
ty = Type::int_type;
|
||||
ConstType* defType = 0;
|
||||
|
||||
if (expr != nullptr) {
|
||||
expr->semant(e);
|
||||
@@ -65,15 +86,19 @@ void VarDeclNode::proto(DeclSeq *d, Environ *e) {
|
||||
}
|
||||
|
||||
if (constant || (kind & DECL_PARAM)) {
|
||||
ConstNode *c = static_cast<ConstNode*>(expr);//->constNode();
|
||||
ConstNode* c = static_cast<ConstNode*>(expr); //->constNode();
|
||||
|
||||
|
||||
if (!c) ex("Expression must be constant");
|
||||
if (ty == Type::int_type) ty = new ConstType(c->intValue());
|
||||
else if (ty == Type::float_type) ty = new ConstType(c->floatValue());
|
||||
else ty = new ConstType(c->stringValue());
|
||||
if (!c)
|
||||
ex("Expression must be constant");
|
||||
if (ty == Type::int_type)
|
||||
ty = new ConstType(c->intValue());
|
||||
else if (ty == Type::float_type)
|
||||
ty = new ConstType(c->floatValue());
|
||||
else
|
||||
ty = new ConstType(c->stringValue());
|
||||
e->types.push_back(ty);
|
||||
delete expr; expr = 0;
|
||||
delete expr;
|
||||
expr = 0;
|
||||
}
|
||||
|
||||
if (expr == nullptr) {
|
||||
@@ -81,55 +106,66 @@ void VarDeclNode::proto(DeclSeq *d, Environ *e) {
|
||||
}
|
||||
|
||||
if (kind & DECL_PARAM) { // Heap corruption, this being replaced again?
|
||||
defType = ty->constType(); ty = defType->valueType;
|
||||
defType = ty->constType();
|
||||
ty = defType->valueType;
|
||||
}
|
||||
} else if (constant) ex("Constants must be initialized");
|
||||
} else if (constant)
|
||||
ex("Constants must be initialized");
|
||||
|
||||
Decl *decl = d->insertDecl(ident, ty, kind, defType);
|
||||
if (!decl) ex("Duplicate variable name");
|
||||
if (expr) sem_var = new DeclVarNode(decl);
|
||||
Decl* decl = d->insertDecl(ident, ty, kind, defType);
|
||||
if (!decl)
|
||||
ex("Duplicate variable name");
|
||||
if (expr)
|
||||
sem_var = new DeclVarNode(decl);
|
||||
}
|
||||
|
||||
void VarDeclNode::semant(Environ *e) {}
|
||||
void VarDeclNode::semant(Environ* e) {}
|
||||
|
||||
void VarDeclNode::translate(Codegen *g) {
|
||||
void VarDeclNode::translate(Codegen* g)
|
||||
{
|
||||
if (kind & DECL_GLOBAL) {
|
||||
g->align_data(4);
|
||||
g->i_data(0, "_v" + ident);
|
||||
}
|
||||
if (expr) g->code(sem_var->store(g, expr->translate(g)));
|
||||
if (expr)
|
||||
g->code(sem_var->store(g, expr->translate(g)));
|
||||
}
|
||||
|
||||
//////////////////////////
|
||||
// Function Declaration //
|
||||
//////////////////////////
|
||||
void FuncDeclNode::proto(DeclSeq *d, Environ *e) {
|
||||
Type *t = tagType(tag, e); if (!t) t = Type::int_type;
|
||||
void FuncDeclNode::proto(DeclSeq* d, Environ* e)
|
||||
{
|
||||
Type* t = tagType(tag, e);
|
||||
if (!t)
|
||||
t = Type::int_type;
|
||||
a_ptr<DeclSeq> decls(new DeclSeq());
|
||||
params->proto(decls, e);
|
||||
sem_type = new FuncType(t, decls.release(), false, false);
|
||||
if (!d->insertDecl(ident, sem_type, DECL_FUNC)) {
|
||||
delete sem_type; ex("duplicate identifier");
|
||||
delete sem_type;
|
||||
ex("duplicate identifier");
|
||||
}
|
||||
e->types.push_back(sem_type);
|
||||
}
|
||||
|
||||
void FuncDeclNode::semant(Environ *e) {
|
||||
|
||||
sem_env = new Environ(genLabel(), sem_type->returnType, 1, e);
|
||||
DeclSeq *decls = sem_env->decls;
|
||||
void FuncDeclNode::semant(Environ* e)
|
||||
{
|
||||
sem_env = new Environ(genLabel(), sem_type->returnType, 1, e);
|
||||
DeclSeq* decls = sem_env->decls;
|
||||
|
||||
int k;
|
||||
for (k = 0; k < sem_type->params->size(); ++k) {
|
||||
Decl *d = sem_type->params->decls[k];
|
||||
if (!decls->insertDecl(d->name, d->type, d->kind)) ex("duplicate identifier");
|
||||
Decl* d = sem_type->params->decls[k];
|
||||
if (!decls->insertDecl(d->name, d->type, d->kind))
|
||||
ex("duplicate identifier");
|
||||
}
|
||||
|
||||
stmts->semant(sem_env);
|
||||
}
|
||||
|
||||
void FuncDeclNode::translate(Codegen *g) {
|
||||
|
||||
void FuncDeclNode::translate(Codegen* g)
|
||||
{
|
||||
//var offsets
|
||||
int size = enumVars(sem_env);
|
||||
|
||||
@@ -137,8 +173,9 @@ void FuncDeclNode::translate(Codegen *g) {
|
||||
g->enter("_f" + ident, size);
|
||||
|
||||
//initialize locals
|
||||
TNode *t = createVars(sem_env);
|
||||
if (t) g->code(t);
|
||||
TNode* t = createVars(sem_env);
|
||||
if (t)
|
||||
g->code(t);
|
||||
if (g->debug) {
|
||||
string t = genLabel();
|
||||
g->s_data(ident, t);
|
||||
@@ -149,34 +186,40 @@ void FuncDeclNode::translate(Codegen *g) {
|
||||
stmts->translate(g);
|
||||
|
||||
for (size_t k = 0; k < sem_env->labels.size(); ++k) {
|
||||
if (sem_env->labels[k]->def < 0) ex("Undefined label", sem_env->labels[k]->ref);
|
||||
if (sem_env->labels[k]->def < 0)
|
||||
ex("Undefined label", sem_env->labels[k]->ref);
|
||||
}
|
||||
|
||||
//leave the function
|
||||
g->label(sem_env->funcLabel + "_leave");
|
||||
t = deleteVars(sem_env);
|
||||
if (g->debug) t = new TNode(IR_SEQ, call("__bbDebugLeave"), t);
|
||||
if (g->debug)
|
||||
t = new TNode(IR_SEQ, call("__bbDebugLeave"), t);
|
||||
g->leave(t, sem_type->params->size() * 4);
|
||||
}
|
||||
|
||||
//////////////////////
|
||||
// Type Declaration //
|
||||
//////////////////////
|
||||
void StructDeclNode::proto(DeclSeq *d, Environ *e) {
|
||||
void StructDeclNode::proto(DeclSeq* d, Environ* e)
|
||||
{
|
||||
sem_type = new StructType(ident, new DeclSeq());
|
||||
if (!d->insertDecl(ident, sem_type, DECL_STRUCT)) {
|
||||
delete sem_type; ex("Duplicate identifier");
|
||||
delete sem_type;
|
||||
ex("Duplicate identifier");
|
||||
}
|
||||
e->types.push_back(sem_type);
|
||||
}
|
||||
|
||||
void StructDeclNode::semant(Environ *e) {
|
||||
void StructDeclNode::semant(Environ* e)
|
||||
{
|
||||
fields->proto(sem_type->fields, e);
|
||||
for (int k = 0; k < sem_type->fields->size(); ++k) sem_type->fields->decls[k]->offset = k * 4;
|
||||
for (int k = 0; k < sem_type->fields->size(); ++k)
|
||||
sem_type->fields->decls[k]->offset = k * 4;
|
||||
}
|
||||
|
||||
void StructDeclNode::translate(Codegen *g) {
|
||||
|
||||
void StructDeclNode::translate(Codegen* g)
|
||||
{
|
||||
//translate fields
|
||||
fields->translate(g);
|
||||
|
||||
@@ -188,11 +231,11 @@ void StructDeclNode::translate(Codegen *g) {
|
||||
int k;
|
||||
for (k = 0; k < 2; ++k) {
|
||||
string lab = genLabel();
|
||||
g->i_data(0, lab); //fields
|
||||
g->p_data(lab); //next
|
||||
g->p_data(lab); //prev
|
||||
g->i_data(0); //type
|
||||
g->i_data(-1); //ref_cnt
|
||||
g->i_data(0, lab); //fields
|
||||
g->p_data(lab); //next
|
||||
g->p_data(lab); //prev
|
||||
g->i_data(0); //type
|
||||
g->i_data(-1); //ref_cnt
|
||||
}
|
||||
|
||||
//number of fields
|
||||
@@ -200,89 +243,115 @@ void StructDeclNode::translate(Codegen *g) {
|
||||
|
||||
//type of each field
|
||||
for (k = 0; k < sem_type->fields->size(); ++k) {
|
||||
Decl *field = sem_type->fields->decls[k];
|
||||
Type *type = field->type;
|
||||
Decl* field = sem_type->fields->decls[k];
|
||||
Type* type = field->type;
|
||||
string t;
|
||||
if (type == Type::int_type) t = "__bbIntType";
|
||||
else if (type == Type::float_type) t = "__bbFltType";
|
||||
else if (type == Type::string_type) t = "__bbStrType";
|
||||
else if (StructType *s = type->structType()) t = "_t" + s->ident;
|
||||
else if (VectorType *v = type->vectorType()) t = v->label;
|
||||
if (type == Type::int_type)
|
||||
t = "__bbIntType";
|
||||
else if (type == Type::float_type)
|
||||
t = "__bbFltType";
|
||||
else if (type == Type::string_type)
|
||||
t = "__bbStrType";
|
||||
else if (StructType* s = type->structType())
|
||||
t = "_t" + s->ident;
|
||||
else if (VectorType* v = type->vectorType())
|
||||
t = v->label;
|
||||
g->p_data(t);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//////////////////////
|
||||
// Data declaration //
|
||||
//////////////////////
|
||||
void DataDeclNode::proto(DeclSeq *d, Environ *e) {
|
||||
expr = expr->semant(e);
|
||||
ConstNode *c = expr->constNode();
|
||||
if (!c) ex("Data expression must be constant");
|
||||
if (expr->sem_type == Type::string_type) str_label = genLabel();
|
||||
void DataDeclNode::proto(DeclSeq* d, Environ* e)
|
||||
{
|
||||
expr = expr->semant(e);
|
||||
ConstNode* c = expr->constNode();
|
||||
if (!c)
|
||||
ex("Data expression must be constant");
|
||||
if (expr->sem_type == Type::string_type)
|
||||
str_label = genLabel();
|
||||
}
|
||||
|
||||
void DataDeclNode::semant(Environ *e) {}
|
||||
void DataDeclNode::semant(Environ* e) {}
|
||||
|
||||
void DataDeclNode::translate(Codegen *g) {
|
||||
if (expr->sem_type != Type::string_type) return;
|
||||
ConstNode *c = expr->constNode();
|
||||
void DataDeclNode::translate(Codegen* g)
|
||||
{
|
||||
if (expr->sem_type != Type::string_type)
|
||||
return;
|
||||
ConstNode* c = expr->constNode();
|
||||
g->s_data(c->stringValue(), str_label);
|
||||
}
|
||||
|
||||
void DataDeclNode::transdata(Codegen *g) {
|
||||
ConstNode *c = expr->constNode();
|
||||
void DataDeclNode::transdata(Codegen* g)
|
||||
{
|
||||
ConstNode* c = expr->constNode();
|
||||
if (expr->sem_type == Type::int_type) {
|
||||
g->i_data(1); g->i_data(c->intValue());
|
||||
g->i_data(1);
|
||||
g->i_data(c->intValue());
|
||||
} else if (expr->sem_type == Type::float_type) {
|
||||
float n = c->floatValue();
|
||||
g->i_data(2); g->i_data(*(int*)&n);
|
||||
g->i_data(2);
|
||||
g->i_data(*(int*)&n);
|
||||
} else {
|
||||
g->i_data(4); g->p_data(str_label);
|
||||
g->i_data(4);
|
||||
g->p_data(str_label);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////
|
||||
// Vector declaration //
|
||||
////////////////////////
|
||||
void VectorDeclNode::proto(DeclSeq *d, Environ *env) {
|
||||
|
||||
Type *ty = tagType(tag, env); if (!ty) ty = Type::int_type;
|
||||
void VectorDeclNode::proto(DeclSeq* d, Environ* env)
|
||||
{
|
||||
Type* ty = tagType(tag, env);
|
||||
if (!ty)
|
||||
ty = Type::int_type;
|
||||
|
||||
vector<int> sizes;
|
||||
for (int k = 0; k < exprs->size(); ++k) {
|
||||
ExprNode *e = exprs->exprs[k] = exprs->exprs[k]->semant(env);
|
||||
ConstNode *c = e->constNode();
|
||||
if (!c) ex("Blitz array sizes must be constant");
|
||||
ExprNode* e = exprs->exprs[k] = exprs->exprs[k]->semant(env);
|
||||
ConstNode* c = e->constNode();
|
||||
if (!c)
|
||||
ex("Blitz array sizes must be constant");
|
||||
int n = c->intValue();
|
||||
if (n < 0) ex("Blitz array sizes must not be negative");
|
||||
if (n < 0)
|
||||
ex("Blitz array sizes must not be negative");
|
||||
sizes.push_back(n + 1);
|
||||
}
|
||||
string label = genLabel();
|
||||
sem_type = new VectorType(label, ty, sizes);
|
||||
sem_type = new VectorType(label, ty, sizes);
|
||||
if (!d->insertDecl(ident, sem_type, kind)) {
|
||||
delete sem_type; ex("Duplicate identifier");
|
||||
delete sem_type;
|
||||
ex("Duplicate identifier");
|
||||
}
|
||||
env->types.push_back(sem_type);
|
||||
}
|
||||
|
||||
void VectorDeclNode::translate(Codegen *g) {
|
||||
void VectorDeclNode::translate(Codegen* g)
|
||||
{
|
||||
//type tag!
|
||||
g->align_data(4);
|
||||
VectorType *v = sem_type->vectorType();
|
||||
VectorType* v = sem_type->vectorType();
|
||||
g->i_data(6, v->label);
|
||||
int sz = 1;
|
||||
for (size_t k = 0; k < v->sizes.size(); ++k) sz *= v->sizes[k];
|
||||
for (size_t k = 0; k < v->sizes.size(); ++k)
|
||||
sz *= v->sizes[k];
|
||||
g->i_data(sz);
|
||||
string t;
|
||||
Type *type = v->elementType;
|
||||
if (type == Type::int_type) t = "__bbIntType";
|
||||
else if (type == Type::float_type) t = "__bbFltType";
|
||||
else if (type == Type::string_type) t = "__bbStrType";
|
||||
else if (StructType *s = type->structType()) t = "_t" + s->ident;
|
||||
else if (VectorType *v = type->vectorType()) t = v->label;
|
||||
Type* type = v->elementType;
|
||||
if (type == Type::int_type)
|
||||
t = "__bbIntType";
|
||||
else if (type == Type::float_type)
|
||||
t = "__bbFltType";
|
||||
else if (type == Type::string_type)
|
||||
t = "__bbStrType";
|
||||
else if (StructType* s = type->structType())
|
||||
t = "_t" + s->ident;
|
||||
else if (VectorType* v = type->vectorType())
|
||||
t = v->label;
|
||||
g->p_data(t);
|
||||
|
||||
if (kind == DECL_GLOBAL) g->i_data(0, "_v" + ident);
|
||||
if (kind == DECL_GLOBAL)
|
||||
g->i_data(0, "_v" + ident);
|
||||
}
|
||||
|
||||
+96
-64
@@ -2,26 +2,36 @@
|
||||
#ifndef DECLNODE_H
|
||||
#define DECLNODE_H
|
||||
|
||||
struct DeclNode : public Node{
|
||||
int pos;
|
||||
struct DeclNode : public Node {
|
||||
int pos;
|
||||
string file;
|
||||
DeclNode():pos(-1){}
|
||||
virtual void proto( DeclSeq *d,Environ *e ){}
|
||||
virtual void semant( Environ *e ){}
|
||||
virtual void translate( Codegen *g ){}
|
||||
virtual void transdata( Codegen *g ){}
|
||||
DeclNode() : pos(-1) {}
|
||||
virtual void proto(DeclSeq* d, Environ* e) {}
|
||||
virtual void semant(Environ* e) {}
|
||||
virtual void translate(Codegen* g) {}
|
||||
virtual void transdata(Codegen* g) {}
|
||||
};
|
||||
|
||||
struct DeclSeqNode : public Node{
|
||||
struct DeclSeqNode : public Node {
|
||||
vector<DeclNode*> decls;
|
||||
DeclSeqNode(){}
|
||||
~DeclSeqNode(){ for(;decls.size();decls.pop_back())delete decls.back(); }
|
||||
void proto( DeclSeq *d,Environ *e );
|
||||
void semant( Environ *e );
|
||||
void translate( Codegen *g );
|
||||
void transdata( Codegen *g );
|
||||
void push_back( DeclNode *d ){ decls.push_back( d ); }
|
||||
int size(){ return decls.size(); }
|
||||
DeclSeqNode() {}
|
||||
~DeclSeqNode()
|
||||
{
|
||||
for (; decls.size(); decls.pop_back())
|
||||
delete decls.back();
|
||||
}
|
||||
void proto(DeclSeq* d, Environ* e);
|
||||
void semant(Environ* e);
|
||||
void translate(Codegen* g);
|
||||
void transdata(Codegen* g);
|
||||
void push_back(DeclNode* d)
|
||||
{
|
||||
decls.push_back(d);
|
||||
}
|
||||
int size()
|
||||
{
|
||||
return decls.size();
|
||||
}
|
||||
};
|
||||
|
||||
#include "exprnode.hpp"
|
||||
@@ -29,62 +39,84 @@ struct DeclSeqNode : public Node{
|
||||
|
||||
//'kind' shouldn't really be in Parser...
|
||||
//should probably be LocalDeclNode,GlobalDeclNode,ParamDeclNode
|
||||
struct VarDeclNode : public DeclNode{
|
||||
string ident,tag;
|
||||
int kind;bool constant;
|
||||
ExprNode *expr;
|
||||
DeclVarNode *sem_var;
|
||||
VarDeclNode( const string &i,const string &t,int k,bool c,ExprNode *e ):ident(i),tag(t),kind(k),constant(c),expr(e),sem_var(0){}
|
||||
~VarDeclNode(){ delete expr;delete sem_var; }
|
||||
void proto( DeclSeq *d,Environ *e );
|
||||
void semant( Environ *e );
|
||||
void translate( Codegen *g );
|
||||
struct VarDeclNode : public DeclNode {
|
||||
string ident, tag;
|
||||
int kind;
|
||||
bool constant;
|
||||
ExprNode* expr;
|
||||
DeclVarNode* sem_var;
|
||||
VarDeclNode(const string& i, const string& t, int k, bool c, ExprNode* e)
|
||||
: ident(i), tag(t), kind(k), constant(c), expr(e), sem_var(0)
|
||||
{}
|
||||
~VarDeclNode()
|
||||
{
|
||||
delete expr;
|
||||
delete sem_var;
|
||||
}
|
||||
void proto(DeclSeq* d, Environ* e);
|
||||
void semant(Environ* e);
|
||||
void translate(Codegen* g);
|
||||
};
|
||||
|
||||
struct FuncDeclNode : public DeclNode{
|
||||
string ident,tag;
|
||||
DeclSeqNode *params;
|
||||
StmtSeqNode *stmts;
|
||||
FuncType *sem_type;
|
||||
Environ *sem_env;
|
||||
FuncDeclNode( const string &i,const string &t,DeclSeqNode *p,StmtSeqNode *ss ):ident(i),tag(t),params(p),stmts(ss){}
|
||||
~FuncDeclNode(){ delete params;delete stmts; }
|
||||
void proto( DeclSeq *d,Environ *e );
|
||||
void semant( Environ *e );
|
||||
void translate( Codegen *g );
|
||||
struct FuncDeclNode : public DeclNode {
|
||||
string ident, tag;
|
||||
DeclSeqNode* params;
|
||||
StmtSeqNode* stmts;
|
||||
FuncType* sem_type;
|
||||
Environ* sem_env;
|
||||
FuncDeclNode(const string& i, const string& t, DeclSeqNode* p, StmtSeqNode* ss)
|
||||
: ident(i), tag(t), params(p), stmts(ss)
|
||||
{}
|
||||
~FuncDeclNode()
|
||||
{
|
||||
delete params;
|
||||
delete stmts;
|
||||
}
|
||||
void proto(DeclSeq* d, Environ* e);
|
||||
void semant(Environ* e);
|
||||
void translate(Codegen* g);
|
||||
};
|
||||
|
||||
struct StructDeclNode : public DeclNode{
|
||||
string ident;
|
||||
DeclSeqNode *fields;
|
||||
StructType *sem_type;
|
||||
StructDeclNode( const string &i,DeclSeqNode *f ):ident(i),fields(f){}
|
||||
~StructDeclNode(){ delete fields; }
|
||||
void proto( DeclSeq *d,Environ *e );
|
||||
void semant( Environ *e );
|
||||
void translate( Codegen *g );
|
||||
struct StructDeclNode : public DeclNode {
|
||||
string ident;
|
||||
DeclSeqNode* fields;
|
||||
StructType* sem_type;
|
||||
StructDeclNode(const string& i, DeclSeqNode* f) : ident(i), fields(f) {}
|
||||
~StructDeclNode()
|
||||
{
|
||||
delete fields;
|
||||
}
|
||||
void proto(DeclSeq* d, Environ* e);
|
||||
void semant(Environ* e);
|
||||
void translate(Codegen* g);
|
||||
};
|
||||
|
||||
struct DataDeclNode : public DeclNode{
|
||||
ExprNode *expr;
|
||||
string str_label;
|
||||
DataDeclNode( ExprNode *e ):expr(e){}
|
||||
~DataDeclNode(){ delete expr; }
|
||||
void proto( DeclSeq *d,Environ *e );
|
||||
void semant( Environ *e );
|
||||
void translate( Codegen *g );
|
||||
void transdata( Codegen *g );
|
||||
struct DataDeclNode : public DeclNode {
|
||||
ExprNode* expr;
|
||||
string str_label;
|
||||
DataDeclNode(ExprNode* e) : expr(e) {}
|
||||
~DataDeclNode()
|
||||
{
|
||||
delete expr;
|
||||
}
|
||||
void proto(DeclSeq* d, Environ* e);
|
||||
void semant(Environ* e);
|
||||
void translate(Codegen* g);
|
||||
void transdata(Codegen* g);
|
||||
};
|
||||
|
||||
struct VectorDeclNode : public DeclNode{
|
||||
string ident,tag;
|
||||
ExprSeqNode *exprs;
|
||||
int kind;
|
||||
VectorType *sem_type;
|
||||
VectorDeclNode( const string &i,const string &t,ExprSeqNode *e,int k ):ident(i),tag(t),exprs(e),kind(k){}
|
||||
~VectorDeclNode(){ delete exprs; }
|
||||
void proto( DeclSeq *d,Environ *e );
|
||||
void translate( Codegen *g );
|
||||
struct VectorDeclNode : public DeclNode {
|
||||
string ident, tag;
|
||||
ExprSeqNode* exprs;
|
||||
int kind;
|
||||
VectorType* sem_type;
|
||||
VectorDeclNode(const string& i, const string& t, ExprSeqNode* e, int k) : ident(i), tag(t), exprs(e), kind(k) {}
|
||||
~VectorDeclNode()
|
||||
{
|
||||
delete exprs;
|
||||
}
|
||||
void proto(DeclSeq* d, Environ* e);
|
||||
void translate(Codegen* g);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
+58
-35
@@ -1,67 +1,90 @@
|
||||
|
||||
#include "std.hpp"
|
||||
#include "environ.hpp"
|
||||
#include "std.hpp"
|
||||
|
||||
Environ::Environ( const string &f,Type *r,int l,Environ *gs )
|
||||
:funcLabel(f),returnType(r),level(l),globals(gs){
|
||||
decls=new DeclSeq();
|
||||
typeDecls=new DeclSeq();
|
||||
funcDecls=new DeclSeq();
|
||||
if( globals ) globals->children.push_back( this );
|
||||
Environ::Environ(const string& f, Type* r, int l, Environ* gs) : funcLabel(f), returnType(r), level(l), globals(gs)
|
||||
{
|
||||
decls = new DeclSeq();
|
||||
typeDecls = new DeclSeq();
|
||||
funcDecls = new DeclSeq();
|
||||
if (globals)
|
||||
globals->children.push_back(this);
|
||||
}
|
||||
|
||||
Environ::~Environ(){
|
||||
if( globals ) globals->children.remove( this );
|
||||
while( children.size() ) delete children.back();
|
||||
for( ;labels.size();labels.pop_back() ) delete labels.back();
|
||||
Environ::~Environ()
|
||||
{
|
||||
if (globals)
|
||||
globals->children.remove(this);
|
||||
while (children.size())
|
||||
delete children.back();
|
||||
for (; labels.size(); labels.pop_back())
|
||||
delete labels.back();
|
||||
|
||||
//delete all types
|
||||
delete decls;
|
||||
delete funcDecls;
|
||||
delete typeDecls;
|
||||
|
||||
for( int k=0;k<types.size();++k ) delete types[k];
|
||||
for (int k = 0; k < types.size(); ++k)
|
||||
delete types[k];
|
||||
}
|
||||
|
||||
Decl *Environ::findDecl( const string &s ){
|
||||
for( Environ *e=this;e;e=e->globals ){
|
||||
if( Decl *d=e->decls->findDecl( s ) ){
|
||||
if( d->kind&(DECL_LOCAL|DECL_PARAM) ){
|
||||
if( e==this ) return d;
|
||||
}else return d;
|
||||
Decl* Environ::findDecl(const string& s)
|
||||
{
|
||||
for (Environ* e = this; e; e = e->globals) {
|
||||
if (Decl* d = e->decls->findDecl(s)) {
|
||||
if (d->kind & (DECL_LOCAL | DECL_PARAM)) {
|
||||
if (e == this)
|
||||
return d;
|
||||
} else
|
||||
return d;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
Decl *Environ::findFunc( const string &s ){
|
||||
for( Environ *e=this;e;e=e->globals ){
|
||||
if( Decl *d=e->funcDecls->findDecl( s ) ) return d;
|
||||
Decl* Environ::findFunc(const string& s)
|
||||
{
|
||||
for (Environ* e = this; e; e = e->globals) {
|
||||
if (Decl* d = e->funcDecls->findDecl(s))
|
||||
return d;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
Type *Environ::findType( const string &s ){
|
||||
if( s=="%" ) return Type::int_type;
|
||||
if( s=="#" ) return Type::float_type;
|
||||
if( s=="$" ) return Type::string_type;
|
||||
for( Environ *e=this;e;e=e->globals ){
|
||||
if( Decl *d=e->typeDecls->findDecl( s ) ) return d->type->structType();
|
||||
Type* Environ::findType(const string& s)
|
||||
{
|
||||
if (s == "%")
|
||||
return Type::int_type;
|
||||
if (s == "#")
|
||||
return Type::float_type;
|
||||
if (s == "$")
|
||||
return Type::string_type;
|
||||
for (Environ* e = this; e; e = e->globals) {
|
||||
if (Decl* d = e->typeDecls->findDecl(s))
|
||||
return d->type->structType();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
Label *Environ::findLabel( const string &s ){
|
||||
for( int k=0;k<labels.size();++k ) if( labels[k]->name==s ) return labels[k];
|
||||
Label* Environ::findLabel(const string& s)
|
||||
{
|
||||
for (int k = 0; k < labels.size(); ++k)
|
||||
if (labels[k]->name == s)
|
||||
return labels[k];
|
||||
return 0;
|
||||
}
|
||||
|
||||
Label *Environ::insertLabel( const string &s,int def,int src,int sz ){
|
||||
Label *l=new Label( s,def,src,sz );
|
||||
labels.push_back( l );return l;
|
||||
Label* Environ::insertLabel(const string& s, int def, int src, int sz)
|
||||
{
|
||||
Label* l = new Label(s, def, src, sz);
|
||||
labels.push_back(l);
|
||||
return l;
|
||||
}
|
||||
|
||||
string Environ::setBreak( const string &s ){
|
||||
string t=breakLabel;
|
||||
breakLabel=s;return t;
|
||||
string Environ::setBreak(const string& s)
|
||||
{
|
||||
string t = breakLabel;
|
||||
breakLabel = s;
|
||||
return t;
|
||||
}
|
||||
|
||||
+18
-18
@@ -8,35 +8,35 @@
|
||||
#ifndef ENVIRON_H
|
||||
#define ENVIRON_H
|
||||
|
||||
#include "type.hpp"
|
||||
#include "decl.hpp"
|
||||
#include "label.hpp"
|
||||
#include "type.hpp"
|
||||
|
||||
class Environ{
|
||||
public:
|
||||
int level;
|
||||
DeclSeq *decls;
|
||||
DeclSeq *funcDecls;
|
||||
DeclSeq *typeDecls;
|
||||
class Environ {
|
||||
public:
|
||||
int level;
|
||||
DeclSeq* decls;
|
||||
DeclSeq* funcDecls;
|
||||
DeclSeq* typeDecls;
|
||||
|
||||
vector<Type*> types;
|
||||
|
||||
vector<Label*> labels;
|
||||
Environ *globals;
|
||||
Type *returnType;
|
||||
string funcLabel,breakLabel;
|
||||
list<Environ*> children; //for delete!
|
||||
Environ* globals;
|
||||
Type* returnType;
|
||||
string funcLabel, breakLabel;
|
||||
list<Environ*> children; //for delete!
|
||||
|
||||
Environ( const string &f,Type *r,int l,Environ *gs );
|
||||
Environ(const string& f, Type* r, int l, Environ* gs);
|
||||
~Environ();
|
||||
|
||||
Decl *findDecl( const string &s );
|
||||
Decl *findFunc( const string &s );
|
||||
Type *findType( const string &s );
|
||||
Label *findLabel( const string &s );
|
||||
Label *insertLabel( const string &s,int def,int src,int sz );
|
||||
Decl* findDecl(const string& s);
|
||||
Decl* findFunc(const string& s);
|
||||
Type* findType(const string& s);
|
||||
Label* findLabel(const string& s);
|
||||
Label* insertLabel(const string& s, int def, int src, int sz);
|
||||
|
||||
string setBreak( const string &s );
|
||||
string setBreak(const string& s);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
+5
-5
@@ -2,12 +2,12 @@
|
||||
#ifndef EX_H
|
||||
#define EX_H
|
||||
|
||||
struct Ex{
|
||||
string ex; //what happened
|
||||
int pos; //source offset
|
||||
struct Ex {
|
||||
string ex; //what happened
|
||||
int pos; //source offset
|
||||
string file;
|
||||
Ex( const string &ex ):ex(ex),pos(-1){}
|
||||
Ex( const string &ex,int pos,const string &t ):ex(ex),pos(pos),file(t){}
|
||||
Ex(const string& ex) : ex(ex), pos(-1) {}
|
||||
Ex(const string& ex, int pos, const string& t) : ex(ex), pos(pos), file(t) {}
|
||||
};
|
||||
|
||||
#endif
|
||||
+410
-194
@@ -1,33 +1,38 @@
|
||||
|
||||
#include "std.hpp"
|
||||
#include "nodes.hpp"
|
||||
#include "std.hpp"
|
||||
|
||||
#include <math.h>
|
||||
#include <float.h>
|
||||
#include <math.h>
|
||||
|
||||
//////////////////////////////////
|
||||
// Cast an expression to a type //
|
||||
//////////////////////////////////
|
||||
ExprNode *ExprNode::castTo(Type *ty, Environ *e) {
|
||||
ExprNode* ExprNode::castTo(Type* ty, Environ* e)
|
||||
{
|
||||
if (!sem_type->canCastTo(ty)) {
|
||||
ex("Illegal type conversion");
|
||||
}
|
||||
|
||||
ExprNode *cast = new CastNode(this, ty);
|
||||
ExprNode* cast = new CastNode(this, ty);
|
||||
cast->semant(e);
|
||||
return cast;
|
||||
}
|
||||
|
||||
ExprNode *CastNode::semant(Environ *e) {
|
||||
ExprNode* CastNode::semant(Environ* e)
|
||||
{
|
||||
if (!expr->sem_type) {
|
||||
expr = expr->semant(e);
|
||||
}
|
||||
|
||||
if (ConstNode *c = expr->constNode()) {
|
||||
ExprNode *e;
|
||||
if (type == Type::int_type) e = new IntConstNode(c->intValue());
|
||||
else if (type == Type::float_type) e = new FloatConstNode(c->floatValue());
|
||||
else e = new StringConstNode(c->stringValue());
|
||||
if (ConstNode* c = expr->constNode()) {
|
||||
ExprNode* e;
|
||||
if (type == Type::int_type)
|
||||
e = new IntConstNode(c->intValue());
|
||||
else if (type == Type::float_type)
|
||||
e = new FloatConstNode(c->floatValue());
|
||||
else
|
||||
e = new StringConstNode(c->stringValue());
|
||||
delete this;
|
||||
return e;
|
||||
}
|
||||
@@ -39,8 +44,9 @@ ExprNode *CastNode::semant(Environ *e) {
|
||||
//////////////////////////////////
|
||||
// Cast an expression to a type //
|
||||
//////////////////////////////////
|
||||
TNode *CastNode::translate(Codegen *g) {
|
||||
TNode *t = expr->translate(g);
|
||||
TNode* CastNode::translate(Codegen* g)
|
||||
{
|
||||
TNode* t = expr->translate(g);
|
||||
if (expr->sem_type == Type::float_type && sem_type == Type::int_type) {
|
||||
//float->int
|
||||
return new TNode(IR_CAST, t, 0);
|
||||
@@ -75,20 +81,22 @@ TNode *CastNode::translate(Codegen *g) {
|
||||
/////////////////////////////
|
||||
// Sequence of Expressions //
|
||||
/////////////////////////////
|
||||
void ExprSeqNode::semant(Environ *e) {
|
||||
void ExprSeqNode::semant(Environ* e)
|
||||
{
|
||||
for (int k = 0; k < exprs.size(); ++k) {
|
||||
if (exprs[k]) exprs[k] = exprs[k]->semant(e);
|
||||
if (exprs[k])
|
||||
exprs[k] = exprs[k]->semant(e);
|
||||
}
|
||||
}
|
||||
|
||||
TNode *ExprSeqNode::translate(Codegen *g, bool cfunc) {
|
||||
TNode* ExprSeqNode::translate(Codegen* g, bool cfunc)
|
||||
{
|
||||
TNode *t = 0, *l = 0;
|
||||
for (int k = 0; k < exprs.size(); ++k) {
|
||||
|
||||
TNode *q = exprs[k]->translate(g);
|
||||
TNode* q = exprs[k]->translate(g);
|
||||
|
||||
if (cfunc) {
|
||||
Type *ty = exprs[k]->sem_type;
|
||||
Type* ty = exprs[k]->sem_type;
|
||||
if (ty->stringType()) {
|
||||
q = call("__bbStrToCStr", q);
|
||||
} else if (ty->structType()) {
|
||||
@@ -98,24 +106,27 @@ TNode *ExprSeqNode::translate(Codegen *g, bool cfunc) {
|
||||
}
|
||||
}
|
||||
|
||||
TNode *p;
|
||||
TNode* p;
|
||||
p = new TNode(IR_ARG, 0, 0, k * 4);
|
||||
p = new TNode(IR_MEM, p, 0);
|
||||
p = new TNode(IR_MOVE, q, p);
|
||||
p = new TNode(IR_SEQ, p, 0);
|
||||
if (l) l->r = p;
|
||||
else t = p;
|
||||
if (l)
|
||||
l->r = p;
|
||||
else
|
||||
t = p;
|
||||
l = p;
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
void ExprSeqNode::castTo(DeclSeq *decls, Environ *e, bool cfunc) {
|
||||
if (exprs.size() > decls->size()) ex("Too many parameters");
|
||||
void ExprSeqNode::castTo(DeclSeq* decls, Environ* e, bool cfunc)
|
||||
{
|
||||
if (exprs.size() > decls->size())
|
||||
ex("Too many parameters");
|
||||
for (int k = 0; k < decls->size(); ++k) {
|
||||
Decl *d = decls->decls[k];
|
||||
Decl* d = decls->decls[k];
|
||||
if (k < exprs.size() && exprs[k]) {
|
||||
|
||||
if (cfunc && d->type->structType()) {
|
||||
if (exprs[k]->sem_type->structType()) {
|
||||
} else if (exprs[k]->sem_type->intType()) {
|
||||
@@ -129,15 +140,19 @@ void ExprSeqNode::castTo(DeclSeq *decls, Environ *e, bool cfunc) {
|
||||
exprs[k] = exprs[k]->castTo(d->type, e);
|
||||
|
||||
} else {
|
||||
if (!d->defType) ex("Not enough parameters");
|
||||
ExprNode *expr = constValue(d->defType);
|
||||
if (k < exprs.size()) exprs[k] = expr;
|
||||
else exprs.push_back(expr);
|
||||
if (!d->defType)
|
||||
ex("Not enough parameters");
|
||||
ExprNode* expr = constValue(d->defType);
|
||||
if (k < exprs.size())
|
||||
exprs[k] = expr;
|
||||
else
|
||||
exprs.push_back(expr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ExprSeqNode::castTo(Type *t, Environ *e) {
|
||||
void ExprSeqNode::castTo(Type* t, Environ* e)
|
||||
{
|
||||
for (int k = 0; k < exprs.size(); ++k) {
|
||||
exprs[k] = exprs[k]->castTo(t, e);
|
||||
}
|
||||
@@ -146,25 +161,28 @@ void ExprSeqNode::castTo(Type *t, Environ *e) {
|
||||
///////////////////
|
||||
// Function call //
|
||||
///////////////////
|
||||
ExprNode *CallNode::semant(Environ *e) {
|
||||
Type *t = e->findType(tag);
|
||||
ExprNode* CallNode::semant(Environ* e)
|
||||
{
|
||||
Type* t = e->findType(tag);
|
||||
sem_decl = e->findFunc(ident);
|
||||
if (!sem_decl || !(sem_decl->kind & DECL_FUNC)) ex("Function '" + ident + "' not found");
|
||||
FuncType *f = sem_decl->type->funcType();
|
||||
if (t && f->returnType != t) ex("incorrect function return type");
|
||||
if (!sem_decl || !(sem_decl->kind & DECL_FUNC))
|
||||
ex("Function '" + ident + "' not found");
|
||||
FuncType* f = sem_decl->type->funcType();
|
||||
if (t && f->returnType != t)
|
||||
ex("incorrect function return type");
|
||||
exprs->semant(e);
|
||||
exprs->castTo(f->params, e, f->cfunc);
|
||||
sem_type = f->returnType;
|
||||
return this;
|
||||
}
|
||||
|
||||
TNode *CallNode::translate(Codegen *g) {
|
||||
TNode* CallNode::translate(Codegen* g)
|
||||
{
|
||||
FuncType* f = sem_decl->type->funcType();
|
||||
|
||||
FuncType *f = sem_decl->type->funcType();
|
||||
|
||||
TNode *t;
|
||||
TNode *l = global("_f" + ident);
|
||||
TNode *r = exprs->translate(g, f->cfunc);
|
||||
TNode* t;
|
||||
TNode* l = global("_f" + ident);
|
||||
TNode* r = exprs->translate(g, f->cfunc);
|
||||
|
||||
if (f->userlib) {
|
||||
l = new TNode(IR_MEM, l);
|
||||
@@ -188,57 +206,71 @@ TNode *CallNode::translate(Codegen *g) {
|
||||
/////////////////////////
|
||||
// Variable expression //
|
||||
/////////////////////////
|
||||
ExprNode *VarExprNode::semant(Environ *e) {
|
||||
ExprNode* VarExprNode::semant(Environ* e)
|
||||
{
|
||||
var->semant(e);
|
||||
sem_type = var->sem_type;
|
||||
ConstType *c = sem_type->constType();
|
||||
if (!c) return this;
|
||||
ExprNode *expr = constValue(c);
|
||||
delete this; return expr;
|
||||
sem_type = var->sem_type;
|
||||
ConstType* c = sem_type->constType();
|
||||
if (!c)
|
||||
return this;
|
||||
ExprNode* expr = constValue(c);
|
||||
delete this;
|
||||
return expr;
|
||||
}
|
||||
|
||||
TNode *VarExprNode::translate(Codegen *g) {
|
||||
TNode* VarExprNode::translate(Codegen* g)
|
||||
{
|
||||
return var->load(g);
|
||||
}
|
||||
|
||||
//////////////////////
|
||||
// Integer constant //
|
||||
//////////////////////
|
||||
IntConstNode::IntConstNode(int n) :value(n) {
|
||||
IntConstNode::IntConstNode(int n) : value(n)
|
||||
{
|
||||
sem_type = Type::int_type;
|
||||
}
|
||||
|
||||
TNode *IntConstNode::translate(Codegen *g) {
|
||||
TNode* IntConstNode::translate(Codegen* g)
|
||||
{
|
||||
return new TNode(IR_CONST, 0, 0, value);
|
||||
}
|
||||
|
||||
int IntConstNode::intValue() {
|
||||
int IntConstNode::intValue()
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
float IntConstNode::floatValue() {
|
||||
float IntConstNode::floatValue()
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
string IntConstNode::stringValue() {
|
||||
string IntConstNode::stringValue()
|
||||
{
|
||||
return itoa(value);
|
||||
}
|
||||
|
||||
////////////////////
|
||||
// Float constant //
|
||||
////////////////////
|
||||
FloatConstNode::FloatConstNode(float f) :value(f) {
|
||||
FloatConstNode::FloatConstNode(float f) : value(f)
|
||||
{
|
||||
sem_type = Type::float_type;
|
||||
}
|
||||
|
||||
TNode *FloatConstNode::translate(Codegen *g) {
|
||||
TNode* FloatConstNode::translate(Codegen* g)
|
||||
{
|
||||
return new TNode(IR_CONST, 0, 0, *(int*)&value);
|
||||
}
|
||||
|
||||
int FloatConstNode::intValue() {
|
||||
int FloatConstNode::intValue()
|
||||
{
|
||||
float flt = value;
|
||||
int temp;
|
||||
_control87(_RC_NEAR | _PC_24 | _EM_INVALID | _EM_ZERODIVIDE | _EM_OVERFLOW | _EM_UNDERFLOW | _EM_INEXACT | _EM_DENORMAL, 0xfffff);
|
||||
int temp;
|
||||
_control87(_RC_NEAR | _PC_24 | _EM_INVALID | _EM_ZERODIVIDE | _EM_OVERFLOW | _EM_UNDERFLOW | _EM_INEXACT
|
||||
| _EM_DENORMAL,
|
||||
0xfffff);
|
||||
_asm {
|
||||
fld[flt];
|
||||
fistp[temp];
|
||||
@@ -247,61 +279,86 @@ int FloatConstNode::intValue() {
|
||||
return temp;
|
||||
}
|
||||
|
||||
float FloatConstNode::floatValue() {
|
||||
float FloatConstNode::floatValue()
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
string FloatConstNode::stringValue() {
|
||||
string FloatConstNode::stringValue()
|
||||
{
|
||||
return ftoa(value);
|
||||
}
|
||||
|
||||
/////////////////////
|
||||
// String constant //
|
||||
/////////////////////
|
||||
StringConstNode::StringConstNode(const string &s) :value(s) {
|
||||
StringConstNode::StringConstNode(const string& s) : value(s)
|
||||
{
|
||||
sem_type = Type::string_type;
|
||||
}
|
||||
|
||||
TNode *StringConstNode::translate(Codegen *g) {
|
||||
TNode* StringConstNode::translate(Codegen* g)
|
||||
{
|
||||
string lab = genLabel();
|
||||
g->s_data(value, lab);
|
||||
return call("__bbStrConst", global(lab));
|
||||
}
|
||||
|
||||
int StringConstNode::intValue() {
|
||||
int StringConstNode::intValue()
|
||||
{
|
||||
return atoi(value);
|
||||
}
|
||||
|
||||
float StringConstNode::floatValue() {
|
||||
float StringConstNode::floatValue()
|
||||
{
|
||||
return (float)atof(value);
|
||||
}
|
||||
|
||||
string StringConstNode::stringValue() {
|
||||
string StringConstNode::stringValue()
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
////////////////////
|
||||
// Unary operator //
|
||||
////////////////////
|
||||
ExprNode *UniExprNode::semant(Environ *e) {
|
||||
expr = expr->semant(e);
|
||||
ExprNode* UniExprNode::semant(Environ* e)
|
||||
{
|
||||
expr = expr->semant(e);
|
||||
sem_type = expr->sem_type;
|
||||
if (sem_type != Type::int_type && sem_type != Type::float_type) ex("Illegal operator for type");
|
||||
if (ConstNode *c = expr->constNode()) {
|
||||
ExprNode *e;
|
||||
if (sem_type != Type::int_type && sem_type != Type::float_type)
|
||||
ex("Illegal operator for type");
|
||||
if (ConstNode* c = expr->constNode()) {
|
||||
ExprNode* e;
|
||||
if (sem_type == Type::int_type) {
|
||||
switch (op) {
|
||||
case '+':e = new IntConstNode(+c->intValue()); break;
|
||||
case '-':e = new IntConstNode(-c->intValue()); break;
|
||||
case ABS:e = new IntConstNode(c->intValue() >= 0 ? c->intValue() : -c->intValue()); break;
|
||||
case SGN:e = new IntConstNode(c->intValue() > 0 ? 1 : (c->intValue() < 0 ? -1 : 0)); break;
|
||||
case '+':
|
||||
e = new IntConstNode(+c->intValue());
|
||||
break;
|
||||
case '-':
|
||||
e = new IntConstNode(-c->intValue());
|
||||
break;
|
||||
case ABS:
|
||||
e = new IntConstNode(c->intValue() >= 0 ? c->intValue() : -c->intValue());
|
||||
break;
|
||||
case SGN:
|
||||
e = new IntConstNode(c->intValue() > 0 ? 1 : (c->intValue() < 0 ? -1 : 0));
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch (op) {
|
||||
case '+':e = new FloatConstNode(+c->floatValue()); break;
|
||||
case '-':e = new FloatConstNode(-c->floatValue()); break;
|
||||
case ABS:e = new FloatConstNode(c->floatValue() >= 0 ? c->floatValue() : -c->floatValue()); break;
|
||||
case SGN:e = new FloatConstNode(c->floatValue() > 0 ? 1 : (c->floatValue() < 0 ? -1 : 0)); break;
|
||||
case '+':
|
||||
e = new FloatConstNode(+c->floatValue());
|
||||
break;
|
||||
case '-':
|
||||
e = new FloatConstNode(-c->floatValue());
|
||||
break;
|
||||
case ABS:
|
||||
e = new FloatConstNode(c->floatValue() >= 0 ? c->floatValue() : -c->floatValue());
|
||||
break;
|
||||
case SGN:
|
||||
e = new FloatConstNode(c->floatValue() > 0 ? 1 : (c->floatValue() < 0 ? -1 : 0));
|
||||
break;
|
||||
}
|
||||
}
|
||||
delete this;
|
||||
@@ -310,22 +367,33 @@ ExprNode *UniExprNode::semant(Environ *e) {
|
||||
return this;
|
||||
}
|
||||
|
||||
TNode *UniExprNode::translate(Codegen *g) {
|
||||
int n = 0;
|
||||
TNode *l = expr->translate(g);
|
||||
TNode* UniExprNode::translate(Codegen* g)
|
||||
{
|
||||
int n = 0;
|
||||
TNode* l = expr->translate(g);
|
||||
if (sem_type == Type::int_type) {
|
||||
switch (op) {
|
||||
case '+':return l;
|
||||
case '-':n = IR_NEG; break;
|
||||
case ABS:return call("__bbAbs", l);
|
||||
case SGN:return call("__bbSgn", l);
|
||||
case '+':
|
||||
return l;
|
||||
case '-':
|
||||
n = IR_NEG;
|
||||
break;
|
||||
case ABS:
|
||||
return call("__bbAbs", l);
|
||||
case SGN:
|
||||
return call("__bbSgn", l);
|
||||
}
|
||||
} else {
|
||||
switch (op) {
|
||||
case '+':return l;
|
||||
case '-':n = IR_FNEG; break;
|
||||
case ABS:return fcall("__bbFAbs", l);
|
||||
case SGN:return fcall("__bbFSgn", l);
|
||||
case '+':
|
||||
return l;
|
||||
case '-':
|
||||
n = IR_FNEG;
|
||||
break;
|
||||
case ABS:
|
||||
return fcall("__bbFAbs", l);
|
||||
case SGN:
|
||||
return fcall("__bbFSgn", l);
|
||||
}
|
||||
}
|
||||
return new TNode(n, l, 0);
|
||||
@@ -334,19 +402,34 @@ TNode *UniExprNode::translate(Codegen *g) {
|
||||
/////////////////////////////////////////////////////
|
||||
// boolean expression - accepts ints, returns ints //
|
||||
/////////////////////////////////////////////////////
|
||||
ExprNode *BinExprNode::semant(Environ *e) {
|
||||
lhs = lhs->semant(e); lhs = lhs->castTo(Type::int_type, e);
|
||||
rhs = rhs->semant(e); rhs = rhs->castTo(Type::int_type, e);
|
||||
ExprNode* BinExprNode::semant(Environ* e)
|
||||
{
|
||||
lhs = lhs->semant(e);
|
||||
lhs = lhs->castTo(Type::int_type, e);
|
||||
rhs = rhs->semant(e);
|
||||
rhs = rhs->castTo(Type::int_type, e);
|
||||
ConstNode *lc = lhs->constNode(), *rc = rhs->constNode();
|
||||
if (lc && rc) {
|
||||
ExprNode *expr = nullptr;
|
||||
ExprNode* expr = nullptr;
|
||||
switch (op) {
|
||||
case AND:expr = new IntConstNode(lc->intValue() & rc->intValue()); break;
|
||||
case OR: expr = new IntConstNode(lc->intValue() | rc->intValue()); break;
|
||||
case XOR:expr = new IntConstNode(lc->intValue() ^ rc->intValue()); break;
|
||||
case SHL:expr = new IntConstNode(lc->intValue() << rc->intValue()); break;
|
||||
case SHR:expr = new IntConstNode((unsigned)lc->intValue() >> rc->intValue()); break;
|
||||
case SAR:expr = new IntConstNode(lc->intValue() >> rc->intValue()); break;
|
||||
case AND:
|
||||
expr = new IntConstNode(lc->intValue() & rc->intValue());
|
||||
break;
|
||||
case OR:
|
||||
expr = new IntConstNode(lc->intValue() | rc->intValue());
|
||||
break;
|
||||
case XOR:
|
||||
expr = new IntConstNode(lc->intValue() ^ rc->intValue());
|
||||
break;
|
||||
case SHL:
|
||||
expr = new IntConstNode(lc->intValue() << rc->intValue());
|
||||
break;
|
||||
case SHR:
|
||||
expr = new IntConstNode((unsigned)lc->intValue() >> rc->intValue());
|
||||
break;
|
||||
case SAR:
|
||||
expr = new IntConstNode(lc->intValue() >> rc->intValue());
|
||||
break;
|
||||
}
|
||||
delete this;
|
||||
return expr;
|
||||
@@ -355,13 +438,30 @@ ExprNode *BinExprNode::semant(Environ *e) {
|
||||
return this;
|
||||
}
|
||||
|
||||
TNode *BinExprNode::translate(Codegen *g) {
|
||||
TNode *l = lhs->translate(g);
|
||||
TNode *r = rhs->translate(g);
|
||||
int n = 0;
|
||||
TNode* BinExprNode::translate(Codegen* g)
|
||||
{
|
||||
TNode* l = lhs->translate(g);
|
||||
TNode* r = rhs->translate(g);
|
||||
int n = 0;
|
||||
switch (op) {
|
||||
case AND:n = IR_AND; break; case OR:n = IR_OR; break; case XOR:n = IR_XOR; break;
|
||||
case SHL:n = IR_SHL; break; case SHR:n = IR_SHR; break; case SAR:n = IR_SAR; break;
|
||||
case AND:
|
||||
n = IR_AND;
|
||||
break;
|
||||
case OR:
|
||||
n = IR_OR;
|
||||
break;
|
||||
case XOR:
|
||||
n = IR_XOR;
|
||||
break;
|
||||
case SHL:
|
||||
n = IR_SHL;
|
||||
break;
|
||||
case SHR:
|
||||
n = IR_SHR;
|
||||
break;
|
||||
case SAR:
|
||||
n = IR_SAR;
|
||||
break;
|
||||
}
|
||||
return new TNode(n, l, r);
|
||||
}
|
||||
@@ -369,7 +469,8 @@ TNode *BinExprNode::translate(Codegen *g) {
|
||||
///////////////////////////
|
||||
// arithmetic expression //
|
||||
///////////////////////////
|
||||
ExprNode *ArithExprNode::semant(Environ *e) {
|
||||
ExprNode* ArithExprNode::semant(Environ* e)
|
||||
{
|
||||
lhs = lhs->semant(e);
|
||||
rhs = rhs->semant(e);
|
||||
if (lhs->sem_type->structType() || rhs->sem_type->structType()) {
|
||||
@@ -377,7 +478,8 @@ ExprNode *ArithExprNode::semant(Environ *e) {
|
||||
}
|
||||
if (lhs->sem_type == Type::string_type || rhs->sem_type == Type::string_type) {
|
||||
//one side is a string - only + operator...
|
||||
if (op != '+') ex("Operator cannot be applied to strings");
|
||||
if (op != '+')
|
||||
ex("Operator cannot be applied to strings");
|
||||
sem_type = Type::string_type;
|
||||
} else if (op == '^' || lhs->sem_type == Type::float_type || rhs->sem_type == Type::float_type) {
|
||||
//It's ^, or one side is a float
|
||||
@@ -386,8 +488,8 @@ ExprNode *ArithExprNode::semant(Environ *e) {
|
||||
//must be 2 ints
|
||||
sem_type = Type::int_type;
|
||||
}
|
||||
lhs = lhs->castTo(sem_type, e);
|
||||
rhs = rhs->castTo(sem_type, e);
|
||||
lhs = lhs->castTo(sem_type, e);
|
||||
rhs = rhs->castTo(sem_type, e);
|
||||
ConstNode *lc = lhs->constNode(), *rc = rhs->constNode();
|
||||
if (rc && (op == '/' || op == MOD)) {
|
||||
if ((sem_type == Type::int_type && !rc->intValue()) || (sem_type == Type::float_type && !rc->floatValue())) {
|
||||
@@ -395,25 +497,47 @@ ExprNode *ArithExprNode::semant(Environ *e) {
|
||||
}
|
||||
}
|
||||
if (lc && rc) {
|
||||
ExprNode *expr = nullptr;
|
||||
ExprNode* expr = nullptr;
|
||||
if (sem_type == Type::string_type) {
|
||||
expr = new StringConstNode(lc->stringValue() + rc->stringValue());
|
||||
} else if (sem_type == Type::int_type) {
|
||||
switch (op) {
|
||||
case '+':expr = new IntConstNode(lc->intValue() + rc->intValue()); break;
|
||||
case '-':expr = new IntConstNode(lc->intValue() - rc->intValue()); break;
|
||||
case '*':expr = new IntConstNode(lc->intValue()*rc->intValue()); break;
|
||||
case '/':expr = new IntConstNode(lc->intValue() / rc->intValue()); break;
|
||||
case MOD:expr = new IntConstNode(lc->intValue() % rc->intValue()); break;
|
||||
case '+':
|
||||
expr = new IntConstNode(lc->intValue() + rc->intValue());
|
||||
break;
|
||||
case '-':
|
||||
expr = new IntConstNode(lc->intValue() - rc->intValue());
|
||||
break;
|
||||
case '*':
|
||||
expr = new IntConstNode(lc->intValue() * rc->intValue());
|
||||
break;
|
||||
case '/':
|
||||
expr = new IntConstNode(lc->intValue() / rc->intValue());
|
||||
break;
|
||||
case MOD:
|
||||
expr = new IntConstNode(lc->intValue() % rc->intValue());
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch (op) {
|
||||
case '+':expr = new FloatConstNode(lc->floatValue() + rc->floatValue()); break;
|
||||
case '-':expr = new FloatConstNode(lc->floatValue() - rc->floatValue()); break;
|
||||
case '*':expr = new FloatConstNode(lc->floatValue()*rc->floatValue()); break;
|
||||
case '/':expr = new FloatConstNode(lc->floatValue() / rc->floatValue()); break;
|
||||
case MOD:expr = new FloatConstNode(fmod(lc->floatValue(), rc->floatValue())); break;
|
||||
case '^':expr = new FloatConstNode(pow(lc->floatValue(), rc->floatValue())); break;
|
||||
case '+':
|
||||
expr = new FloatConstNode(lc->floatValue() + rc->floatValue());
|
||||
break;
|
||||
case '-':
|
||||
expr = new FloatConstNode(lc->floatValue() - rc->floatValue());
|
||||
break;
|
||||
case '*':
|
||||
expr = new FloatConstNode(lc->floatValue() * rc->floatValue());
|
||||
break;
|
||||
case '/':
|
||||
expr = new FloatConstNode(lc->floatValue() / rc->floatValue());
|
||||
break;
|
||||
case MOD:
|
||||
expr = new FloatConstNode(fmod(lc->floatValue(), rc->floatValue()));
|
||||
break;
|
||||
case '^':
|
||||
expr = new FloatConstNode(pow(lc->floatValue(), rc->floatValue()));
|
||||
break;
|
||||
}
|
||||
}
|
||||
delete this;
|
||||
@@ -422,25 +546,49 @@ ExprNode *ArithExprNode::semant(Environ *e) {
|
||||
return this;
|
||||
}
|
||||
|
||||
TNode *ArithExprNode::translate(Codegen *g) {
|
||||
TNode *l = lhs->translate(g);
|
||||
TNode *r = rhs->translate(g);
|
||||
TNode* ArithExprNode::translate(Codegen* g)
|
||||
{
|
||||
TNode* l = lhs->translate(g);
|
||||
TNode* r = rhs->translate(g);
|
||||
if (sem_type == Type::string_type) {
|
||||
return call("__bbStrConcat", l, r);
|
||||
}
|
||||
int n = 0;
|
||||
if (sem_type == Type::int_type) {
|
||||
switch (op) {
|
||||
case '+':n = IR_ADD; break; case '-':n = IR_SUB; break;
|
||||
case '*':n = IR_MUL; break; case '/':n = IR_DIV; break;
|
||||
case MOD:return call("__bbMod", l, r);
|
||||
case '+':
|
||||
n = IR_ADD;
|
||||
break;
|
||||
case '-':
|
||||
n = IR_SUB;
|
||||
break;
|
||||
case '*':
|
||||
n = IR_MUL;
|
||||
break;
|
||||
case '/':
|
||||
n = IR_DIV;
|
||||
break;
|
||||
case MOD:
|
||||
return call("__bbMod", l, r);
|
||||
}
|
||||
} else {
|
||||
switch (op) {
|
||||
case '+':n = IR_FADD; break; case '-':n = IR_FSUB; break;
|
||||
case '*':n = IR_FMUL; break; case '/':n = IR_FDIV; break;
|
||||
case MOD:return fcall("__bbFMod", l, r);
|
||||
case '^':return fcall("__bbFPow", l, r);
|
||||
case '+':
|
||||
n = IR_FADD;
|
||||
break;
|
||||
case '-':
|
||||
n = IR_FSUB;
|
||||
break;
|
||||
case '*':
|
||||
n = IR_FMUL;
|
||||
break;
|
||||
case '/':
|
||||
n = IR_FDIV;
|
||||
break;
|
||||
case MOD:
|
||||
return fcall("__bbFMod", l, r);
|
||||
case '^':
|
||||
return fcall("__bbFPow", l, r);
|
||||
}
|
||||
}
|
||||
return new TNode(n, l, r);
|
||||
@@ -449,11 +597,13 @@ TNode *ArithExprNode::translate(Codegen *g) {
|
||||
/////////////////////////
|
||||
// relation expression //
|
||||
/////////////////////////
|
||||
ExprNode *RelExprNode::semant(Environ *e) {
|
||||
ExprNode* RelExprNode::semant(Environ* e)
|
||||
{
|
||||
lhs = lhs->semant(e);
|
||||
rhs = rhs->semant(e);
|
||||
if (lhs->sem_type->structType() || rhs->sem_type->structType()) {
|
||||
if (op != '=' && op != NE) ex("Illegal operator for custom type objects");
|
||||
if (op != '=' && op != NE)
|
||||
ex("Illegal operator for custom type objects");
|
||||
opType = lhs->sem_type != Type::null_type ? lhs->sem_type : rhs->sem_type;
|
||||
} else if (lhs->sem_type == Type::string_type || rhs->sem_type == Type::string_type) {
|
||||
opType = Type::string_type;
|
||||
@@ -462,38 +612,74 @@ ExprNode *RelExprNode::semant(Environ *e) {
|
||||
} else {
|
||||
opType = Type::int_type;
|
||||
}
|
||||
sem_type = Type::int_type;
|
||||
lhs = lhs->castTo(opType, e);
|
||||
rhs = rhs->castTo(opType, e);
|
||||
sem_type = Type::int_type;
|
||||
lhs = lhs->castTo(opType, e);
|
||||
rhs = rhs->castTo(opType, e);
|
||||
ConstNode *lc = lhs->constNode(), *rc = rhs->constNode();
|
||||
if (lc && rc) {
|
||||
ExprNode *expr = nullptr;
|
||||
ExprNode* expr = nullptr;
|
||||
if (opType == Type::string_type) {
|
||||
switch (op) {
|
||||
case '<':expr = new IntConstNode(lc->stringValue() < rc->stringValue()); break;
|
||||
case '=':expr = new IntConstNode(lc->stringValue() == rc->stringValue()); break;
|
||||
case '>':expr = new IntConstNode(lc->stringValue() > rc->stringValue()); break;
|
||||
case LE: expr = new IntConstNode(lc->stringValue() <= rc->stringValue()); break;
|
||||
case NE: expr = new IntConstNode(lc->stringValue() != rc->stringValue()); break;
|
||||
case GE: expr = new IntConstNode(lc->stringValue() >= rc->stringValue()); break;
|
||||
case '<':
|
||||
expr = new IntConstNode(lc->stringValue() < rc->stringValue());
|
||||
break;
|
||||
case '=':
|
||||
expr = new IntConstNode(lc->stringValue() == rc->stringValue());
|
||||
break;
|
||||
case '>':
|
||||
expr = new IntConstNode(lc->stringValue() > rc->stringValue());
|
||||
break;
|
||||
case LE:
|
||||
expr = new IntConstNode(lc->stringValue() <= rc->stringValue());
|
||||
break;
|
||||
case NE:
|
||||
expr = new IntConstNode(lc->stringValue() != rc->stringValue());
|
||||
break;
|
||||
case GE:
|
||||
expr = new IntConstNode(lc->stringValue() >= rc->stringValue());
|
||||
break;
|
||||
}
|
||||
} else if (opType == Type::float_type) {
|
||||
switch (op) {
|
||||
case '<':expr = new IntConstNode(lc->floatValue() < rc->floatValue()); break;
|
||||
case '=':expr = new IntConstNode(lc->floatValue() == rc->floatValue()); break;
|
||||
case '>':expr = new IntConstNode(lc->floatValue() > rc->floatValue()); break;
|
||||
case LE: expr = new IntConstNode(lc->floatValue() <= rc->floatValue()); break;
|
||||
case NE: expr = new IntConstNode(lc->floatValue() != rc->floatValue()); break;
|
||||
case GE: expr = new IntConstNode(lc->floatValue() >= rc->floatValue()); break;
|
||||
case '<':
|
||||
expr = new IntConstNode(lc->floatValue() < rc->floatValue());
|
||||
break;
|
||||
case '=':
|
||||
expr = new IntConstNode(lc->floatValue() == rc->floatValue());
|
||||
break;
|
||||
case '>':
|
||||
expr = new IntConstNode(lc->floatValue() > rc->floatValue());
|
||||
break;
|
||||
case LE:
|
||||
expr = new IntConstNode(lc->floatValue() <= rc->floatValue());
|
||||
break;
|
||||
case NE:
|
||||
expr = new IntConstNode(lc->floatValue() != rc->floatValue());
|
||||
break;
|
||||
case GE:
|
||||
expr = new IntConstNode(lc->floatValue() >= rc->floatValue());
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch (op) {
|
||||
case '<':expr = new IntConstNode(lc->intValue() < rc->intValue()); break;
|
||||
case '=':expr = new IntConstNode(lc->intValue() == rc->intValue()); break;
|
||||
case '>':expr = new IntConstNode(lc->intValue() > rc->intValue()); break;
|
||||
case LE: expr = new IntConstNode(lc->intValue() <= rc->intValue()); break;
|
||||
case NE: expr = new IntConstNode(lc->intValue() != rc->intValue()); break;
|
||||
case GE: expr = new IntConstNode(lc->intValue() >= rc->intValue()); break;
|
||||
case '<':
|
||||
expr = new IntConstNode(lc->intValue() < rc->intValue());
|
||||
break;
|
||||
case '=':
|
||||
expr = new IntConstNode(lc->intValue() == rc->intValue());
|
||||
break;
|
||||
case '>':
|
||||
expr = new IntConstNode(lc->intValue() > rc->intValue());
|
||||
break;
|
||||
case LE:
|
||||
expr = new IntConstNode(lc->intValue() <= rc->intValue());
|
||||
break;
|
||||
case NE:
|
||||
expr = new IntConstNode(lc->intValue() != rc->intValue());
|
||||
break;
|
||||
case GE:
|
||||
expr = new IntConstNode(lc->intValue() >= rc->intValue());
|
||||
break;
|
||||
}
|
||||
}
|
||||
delete this;
|
||||
@@ -502,127 +688,157 @@ ExprNode *RelExprNode::semant(Environ *e) {
|
||||
return this;
|
||||
}
|
||||
|
||||
TNode *RelExprNode::translate(Codegen *g) {
|
||||
TNode *l = lhs->translate(g);
|
||||
TNode *r = rhs->translate(g);
|
||||
TNode* RelExprNode::translate(Codegen* g)
|
||||
{
|
||||
TNode* l = lhs->translate(g);
|
||||
TNode* r = rhs->translate(g);
|
||||
return compare(op, l, r, opType);
|
||||
}
|
||||
|
||||
////////////////////
|
||||
// New expression //
|
||||
////////////////////
|
||||
ExprNode *NewNode::semant(Environ *e) {
|
||||
ExprNode* NewNode::semant(Environ* e)
|
||||
{
|
||||
sem_type = e->findType(ident);
|
||||
if (!sem_type) ex("custom type name not found");
|
||||
if (sem_type->structType() == 0) ex("type is not a custom type");
|
||||
if (!sem_type)
|
||||
ex("custom type name not found");
|
||||
if (sem_type->structType() == 0)
|
||||
ex("type is not a custom type");
|
||||
return this;
|
||||
}
|
||||
|
||||
TNode *NewNode::translate(Codegen *g) {
|
||||
TNode* NewNode::translate(Codegen* g)
|
||||
{
|
||||
return call("__bbObjNew", global("_t" + ident));
|
||||
}
|
||||
|
||||
////////////////////
|
||||
// First of class //
|
||||
////////////////////
|
||||
ExprNode *FirstNode::semant(Environ *e) {
|
||||
ExprNode* FirstNode::semant(Environ* e)
|
||||
{
|
||||
sem_type = e->findType(ident);
|
||||
if (!sem_type) ex("custom type name name not found");
|
||||
if (!sem_type)
|
||||
ex("custom type name name not found");
|
||||
return this;
|
||||
}
|
||||
|
||||
TNode *FirstNode::translate(Codegen *g) {
|
||||
TNode* FirstNode::translate(Codegen* g)
|
||||
{
|
||||
return call("__bbObjFirst", global("_t" + ident));
|
||||
}
|
||||
|
||||
///////////////////
|
||||
// Last of class //
|
||||
///////////////////
|
||||
ExprNode *LastNode::semant(Environ *e) {
|
||||
ExprNode* LastNode::semant(Environ* e)
|
||||
{
|
||||
sem_type = e->findType(ident);
|
||||
if (!sem_type) ex("custom type name not found");
|
||||
if (!sem_type)
|
||||
ex("custom type name not found");
|
||||
return this;
|
||||
}
|
||||
|
||||
TNode *LastNode::translate(Codegen *g) {
|
||||
TNode* LastNode::translate(Codegen* g)
|
||||
{
|
||||
return call("__bbObjLast", global("_t" + ident));
|
||||
}
|
||||
|
||||
////////////////////
|
||||
// Next of object //
|
||||
////////////////////
|
||||
ExprNode *AfterNode::semant(Environ *e) {
|
||||
ExprNode* AfterNode::semant(Environ* e)
|
||||
{
|
||||
expr = expr->semant(e);
|
||||
if (expr->sem_type == Type::null_type) ex("'After' cannot be used on 'Null'");
|
||||
if (expr->sem_type->structType() == 0) ex("'After' must be used with a custom type object");
|
||||
if (expr->sem_type == Type::null_type)
|
||||
ex("'After' cannot be used on 'Null'");
|
||||
if (expr->sem_type->structType() == 0)
|
||||
ex("'After' must be used with a custom type object");
|
||||
sem_type = expr->sem_type;
|
||||
return this;
|
||||
}
|
||||
|
||||
TNode *AfterNode::translate(Codegen *g) {
|
||||
TNode *t = expr->translate(g);
|
||||
if (g->debug) t = jumpf(t, "__bbNullObjEx");
|
||||
TNode* AfterNode::translate(Codegen* g)
|
||||
{
|
||||
TNode* t = expr->translate(g);
|
||||
if (g->debug)
|
||||
t = jumpf(t, "__bbNullObjEx");
|
||||
return call("__bbObjNext", t);
|
||||
}
|
||||
|
||||
////////////////////
|
||||
// Prev of object //
|
||||
////////////////////
|
||||
ExprNode *BeforeNode::semant(Environ *e) {
|
||||
ExprNode* BeforeNode::semant(Environ* e)
|
||||
{
|
||||
expr = expr->semant(e);
|
||||
if (expr->sem_type == Type::null_type) ex("'Before' cannot be used with 'Null'");
|
||||
if (expr->sem_type->structType() == 0) ex("'Before' must be used with a custom type object");
|
||||
if (expr->sem_type == Type::null_type)
|
||||
ex("'Before' cannot be used with 'Null'");
|
||||
if (expr->sem_type->structType() == 0)
|
||||
ex("'Before' must be used with a custom type object");
|
||||
sem_type = expr->sem_type;
|
||||
return this;
|
||||
}
|
||||
|
||||
TNode *BeforeNode::translate(Codegen *g) {
|
||||
TNode *t = expr->translate(g);
|
||||
if (g->debug) t = jumpf(t, "__bbNullObjEx");
|
||||
TNode* BeforeNode::translate(Codegen* g)
|
||||
{
|
||||
TNode* t = expr->translate(g);
|
||||
if (g->debug)
|
||||
t = jumpf(t, "__bbNullObjEx");
|
||||
return call("__bbObjPrev", t);
|
||||
}
|
||||
|
||||
/////////////////
|
||||
// Null object //
|
||||
/////////////////
|
||||
ExprNode *NullNode::semant(Environ *e) {
|
||||
ExprNode* NullNode::semant(Environ* e)
|
||||
{
|
||||
sem_type = Type::null_type;
|
||||
return this;
|
||||
}
|
||||
|
||||
TNode *NullNode::translate(Codegen *g) {
|
||||
TNode* NullNode::translate(Codegen* g)
|
||||
{
|
||||
return new TNode(IR_CONST, 0, 0, 0);
|
||||
}
|
||||
|
||||
/////////////////
|
||||
// Object cast //
|
||||
/////////////////
|
||||
ExprNode *ObjectCastNode::semant(Environ *e) {
|
||||
expr = expr->semant(e);
|
||||
expr = expr->castTo(Type::int_type, e);
|
||||
ExprNode* ObjectCastNode::semant(Environ* e)
|
||||
{
|
||||
expr = expr->semant(e);
|
||||
expr = expr->castTo(Type::int_type, e);
|
||||
sem_type = e->findType(type_ident);
|
||||
if (!sem_type) ex("custom type name not found");
|
||||
if (!sem_type->structType()) ex("type is not a custom type");
|
||||
if (!sem_type)
|
||||
ex("custom type name not found");
|
||||
if (!sem_type->structType())
|
||||
ex("type is not a custom type");
|
||||
return this;
|
||||
}
|
||||
|
||||
TNode *ObjectCastNode::translate(Codegen *g) {
|
||||
TNode *t = expr->translate(g);
|
||||
t = call("__bbObjFromHandle", t, global("_t" + sem_type->structType()->ident));
|
||||
TNode* ObjectCastNode::translate(Codegen* g)
|
||||
{
|
||||
TNode* t = expr->translate(g);
|
||||
t = call("__bbObjFromHandle", t, global("_t" + sem_type->structType()->ident));
|
||||
return t;
|
||||
}
|
||||
|
||||
///////////////////
|
||||
// Object Handle //
|
||||
///////////////////
|
||||
ExprNode *ObjectHandleNode::semant(Environ *e) {
|
||||
ExprNode* ObjectHandleNode::semant(Environ* e)
|
||||
{
|
||||
expr = expr->semant(e);
|
||||
if (!expr->sem_type->structType()) ex("'ObjectHandle' must be used with an object");
|
||||
if (!expr->sem_type->structType())
|
||||
ex("'ObjectHandle' must be used with an object");
|
||||
sem_type = Type::int_type;
|
||||
return this;
|
||||
}
|
||||
|
||||
TNode *ObjectHandleNode::translate(Codegen *g) {
|
||||
TNode *t = expr->translate(g);
|
||||
TNode* ObjectHandleNode::translate(Codegen* g)
|
||||
{
|
||||
TNode* t = expr->translate(g);
|
||||
return call("__bbObjToHandle", t);
|
||||
}
|
||||
|
||||
+161
-102
@@ -4,190 +4,249 @@
|
||||
|
||||
#include "node.hpp"
|
||||
|
||||
struct ConstNode; //is constant int,float or string
|
||||
struct ConstNode; //is constant int,float or string
|
||||
|
||||
struct ExprNode : public Node {
|
||||
Type *sem_type;
|
||||
ExprNode() :sem_type(0) {}
|
||||
ExprNode(Type *t) :sem_type(t) {}
|
||||
Type* sem_type;
|
||||
ExprNode() : sem_type(0) {}
|
||||
ExprNode(Type* t) : sem_type(t) {}
|
||||
|
||||
ExprNode *castTo(Type *ty, Environ *e);
|
||||
ExprNode *semant(Environ *e, Type *ty);
|
||||
ExprNode* castTo(Type* ty, Environ* e);
|
||||
ExprNode* semant(Environ* e, Type* ty);
|
||||
|
||||
virtual ExprNode *semant(Environ *e) = 0;
|
||||
virtual TNode *translate(Codegen *g) = 0;
|
||||
virtual ConstNode *constNode() { return 0; }
|
||||
virtual ExprNode* semant(Environ* e) = 0;
|
||||
virtual TNode* translate(Codegen* g) = 0;
|
||||
virtual ConstNode* constNode()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
struct ExprSeqNode : public Node {
|
||||
vector<ExprNode*> exprs;
|
||||
~ExprSeqNode() { for (; exprs.size(); exprs.pop_back()) delete exprs.back(); }
|
||||
void push_back(ExprNode *e) { exprs.push_back(e); }
|
||||
int size() { return exprs.size(); }
|
||||
void semant(Environ *e);
|
||||
TNode *translate(Codegen *g, bool userlib);
|
||||
void castTo(DeclSeq *ds, Environ *e, bool userlib);
|
||||
void castTo(Type *t, Environ *e);
|
||||
~ExprSeqNode()
|
||||
{
|
||||
for (; exprs.size(); exprs.pop_back())
|
||||
delete exprs.back();
|
||||
}
|
||||
void push_back(ExprNode* e)
|
||||
{
|
||||
exprs.push_back(e);
|
||||
}
|
||||
int size()
|
||||
{
|
||||
return exprs.size();
|
||||
}
|
||||
void semant(Environ* e);
|
||||
TNode* translate(Codegen* g, bool userlib);
|
||||
void castTo(DeclSeq* ds, Environ* e, bool userlib);
|
||||
void castTo(Type* t, Environ* e);
|
||||
};
|
||||
|
||||
#include "varnode.hpp"
|
||||
|
||||
struct CastNode : public ExprNode {
|
||||
ExprNode *expr;
|
||||
Type *type;
|
||||
CastNode(ExprNode *ex, Type *ty) :expr(ex), type(ty) {}
|
||||
~CastNode() { delete expr; }
|
||||
ExprNode *semant(Environ *e);
|
||||
TNode *translate(Codegen *g);
|
||||
ExprNode* expr;
|
||||
Type* type;
|
||||
CastNode(ExprNode* ex, Type* ty) : expr(ex), type(ty) {}
|
||||
~CastNode()
|
||||
{
|
||||
delete expr;
|
||||
}
|
||||
ExprNode* semant(Environ* e);
|
||||
TNode* translate(Codegen* g);
|
||||
};
|
||||
|
||||
struct CallNode : public ExprNode {
|
||||
string ident, tag;
|
||||
ExprSeqNode *exprs;
|
||||
Decl *sem_decl;
|
||||
CallNode(const string &i, const string &t, ExprSeqNode *e) :ident(i), tag(t), exprs(e) {}
|
||||
~CallNode() { delete exprs; }
|
||||
ExprNode *semant(Environ *e);
|
||||
TNode *translate(Codegen *g);
|
||||
string ident, tag;
|
||||
ExprSeqNode* exprs;
|
||||
Decl* sem_decl;
|
||||
CallNode(const string& i, const string& t, ExprSeqNode* e) : ident(i), tag(t), exprs(e) {}
|
||||
~CallNode()
|
||||
{
|
||||
delete exprs;
|
||||
}
|
||||
ExprNode* semant(Environ* e);
|
||||
TNode* translate(Codegen* g);
|
||||
};
|
||||
|
||||
struct VarExprNode : public ExprNode {
|
||||
VarNode *var;
|
||||
VarExprNode(VarNode *v) :var(v) {}
|
||||
~VarExprNode() { delete var; }
|
||||
ExprNode *semant(Environ *e);
|
||||
TNode *translate(Codegen *g);
|
||||
VarNode* var;
|
||||
VarExprNode(VarNode* v) : var(v) {}
|
||||
~VarExprNode()
|
||||
{
|
||||
delete var;
|
||||
}
|
||||
ExprNode* semant(Environ* e);
|
||||
TNode* translate(Codegen* g);
|
||||
};
|
||||
|
||||
struct ConstNode : public ExprNode {
|
||||
ExprNode *semant(Environ *e) { return this; }
|
||||
ConstNode *constNode() { return this; }
|
||||
virtual int intValue() = 0;
|
||||
virtual float floatValue() = 0;
|
||||
ExprNode* semant(Environ* e)
|
||||
{
|
||||
return this;
|
||||
}
|
||||
ConstNode* constNode()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
virtual int intValue() = 0;
|
||||
virtual float floatValue() = 0;
|
||||
virtual string stringValue() = 0;
|
||||
};
|
||||
|
||||
struct IntConstNode : public ConstNode {
|
||||
int value;
|
||||
IntConstNode(int n);
|
||||
TNode *translate(Codegen *g);
|
||||
int intValue();
|
||||
float floatValue();
|
||||
TNode* translate(Codegen* g);
|
||||
int intValue();
|
||||
float floatValue();
|
||||
string stringValue();
|
||||
};
|
||||
|
||||
struct FloatConstNode : public ConstNode {
|
||||
float value;
|
||||
FloatConstNode(float f);
|
||||
TNode *translate(Codegen *g);
|
||||
int intValue();
|
||||
float floatValue();
|
||||
TNode* translate(Codegen* g);
|
||||
int intValue();
|
||||
float floatValue();
|
||||
string stringValue();
|
||||
};
|
||||
|
||||
struct StringConstNode : public ConstNode {
|
||||
string value;
|
||||
StringConstNode(const string &s);
|
||||
TNode *translate(Codegen *g);
|
||||
int intValue();
|
||||
float floatValue();
|
||||
StringConstNode(const string& s);
|
||||
TNode* translate(Codegen* g);
|
||||
int intValue();
|
||||
float floatValue();
|
||||
string stringValue();
|
||||
};
|
||||
|
||||
struct UniExprNode : public ExprNode {
|
||||
int op; ExprNode *expr;
|
||||
UniExprNode(int op, ExprNode *expr) :op(op), expr(expr) {}
|
||||
~UniExprNode() { delete expr; }
|
||||
ExprNode *constize();
|
||||
ExprNode *semant(Environ *e);
|
||||
TNode *translate(Codegen *g);
|
||||
int op;
|
||||
ExprNode* expr;
|
||||
UniExprNode(int op, ExprNode* expr) : op(op), expr(expr) {}
|
||||
~UniExprNode()
|
||||
{
|
||||
delete expr;
|
||||
}
|
||||
ExprNode* constize();
|
||||
ExprNode* semant(Environ* e);
|
||||
TNode* translate(Codegen* g);
|
||||
};
|
||||
|
||||
// and, or, eor, lsl, lsr, asr
|
||||
struct BinExprNode : public ExprNode {
|
||||
int op; ExprNode *lhs, *rhs;
|
||||
BinExprNode(int op, ExprNode *lhs, ExprNode *rhs) :op(op), lhs(lhs), rhs(rhs) {}
|
||||
~BinExprNode() { delete lhs; delete rhs; }
|
||||
ExprNode *semant(Environ *e);
|
||||
TNode *translate(Codegen *g);
|
||||
int op;
|
||||
ExprNode *lhs, *rhs;
|
||||
BinExprNode(int op, ExprNode* lhs, ExprNode* rhs) : op(op), lhs(lhs), rhs(rhs) {}
|
||||
~BinExprNode()
|
||||
{
|
||||
delete lhs;
|
||||
delete rhs;
|
||||
}
|
||||
ExprNode* semant(Environ* e);
|
||||
TNode* translate(Codegen* g);
|
||||
};
|
||||
|
||||
// *,/,Mod,+,-
|
||||
struct ArithExprNode : public ExprNode {
|
||||
int op; ExprNode *lhs, *rhs;
|
||||
ArithExprNode(int op, ExprNode *lhs, ExprNode *rhs) :op(op), lhs(lhs), rhs(rhs) {}
|
||||
~ArithExprNode() { delete lhs; delete rhs; }
|
||||
ExprNode *semant(Environ *e);
|
||||
TNode *translate(Codegen *g);
|
||||
int op;
|
||||
ExprNode *lhs, *rhs;
|
||||
ArithExprNode(int op, ExprNode* lhs, ExprNode* rhs) : op(op), lhs(lhs), rhs(rhs) {}
|
||||
~ArithExprNode()
|
||||
{
|
||||
delete lhs;
|
||||
delete rhs;
|
||||
}
|
||||
ExprNode* semant(Environ* e);
|
||||
TNode* translate(Codegen* g);
|
||||
};
|
||||
|
||||
//<,=,>,<=,<>,>=
|
||||
struct RelExprNode : public ExprNode {
|
||||
int op; ExprNode *lhs, *rhs;
|
||||
Type *opType;
|
||||
RelExprNode(int op, ExprNode *lhs, ExprNode *rhs) :op(op), lhs(lhs), rhs(rhs) {}
|
||||
~RelExprNode() { delete lhs; delete rhs; }
|
||||
ExprNode *semant(Environ *e);
|
||||
TNode *translate(Codegen *g);
|
||||
int op;
|
||||
ExprNode *lhs, *rhs;
|
||||
Type* opType;
|
||||
RelExprNode(int op, ExprNode* lhs, ExprNode* rhs) : op(op), lhs(lhs), rhs(rhs) {}
|
||||
~RelExprNode()
|
||||
{
|
||||
delete lhs;
|
||||
delete rhs;
|
||||
}
|
||||
ExprNode* semant(Environ* e);
|
||||
TNode* translate(Codegen* g);
|
||||
};
|
||||
|
||||
struct NewNode : public ExprNode {
|
||||
string ident;
|
||||
NewNode(const string &i) :ident(i) {}
|
||||
ExprNode *semant(Environ *e);
|
||||
TNode *translate(Codegen *g);
|
||||
NewNode(const string& i) : ident(i) {}
|
||||
ExprNode* semant(Environ* e);
|
||||
TNode* translate(Codegen* g);
|
||||
};
|
||||
|
||||
struct FirstNode : public ExprNode {
|
||||
string ident;
|
||||
FirstNode(const string &i) :ident(i) {}
|
||||
ExprNode *semant(Environ *e);
|
||||
TNode *translate(Codegen *g);
|
||||
FirstNode(const string& i) : ident(i) {}
|
||||
ExprNode* semant(Environ* e);
|
||||
TNode* translate(Codegen* g);
|
||||
};
|
||||
|
||||
struct LastNode : public ExprNode {
|
||||
string ident;
|
||||
LastNode(const string &i) :ident(i) {}
|
||||
ExprNode *semant(Environ *e);
|
||||
TNode *translate(Codegen *g);
|
||||
LastNode(const string& i) : ident(i) {}
|
||||
ExprNode* semant(Environ* e);
|
||||
TNode* translate(Codegen* g);
|
||||
};
|
||||
|
||||
struct AfterNode : public ExprNode {
|
||||
ExprNode *expr;
|
||||
AfterNode(ExprNode *e) :expr(e) {}
|
||||
~AfterNode() { delete expr; }
|
||||
ExprNode *semant(Environ *e);
|
||||
TNode *translate(Codegen *g);
|
||||
ExprNode* expr;
|
||||
AfterNode(ExprNode* e) : expr(e) {}
|
||||
~AfterNode()
|
||||
{
|
||||
delete expr;
|
||||
}
|
||||
ExprNode* semant(Environ* e);
|
||||
TNode* translate(Codegen* g);
|
||||
};
|
||||
|
||||
struct BeforeNode : public ExprNode {
|
||||
ExprNode *expr;
|
||||
BeforeNode(ExprNode *e) :expr(e) {}
|
||||
~BeforeNode() { delete expr; }
|
||||
ExprNode *semant(Environ *e);
|
||||
TNode *translate(Codegen *g);
|
||||
ExprNode* expr;
|
||||
BeforeNode(ExprNode* e) : expr(e) {}
|
||||
~BeforeNode()
|
||||
{
|
||||
delete expr;
|
||||
}
|
||||
ExprNode* semant(Environ* e);
|
||||
TNode* translate(Codegen* g);
|
||||
};
|
||||
|
||||
struct NullNode : public ExprNode {
|
||||
ExprNode *semant(Environ *e);
|
||||
TNode *translate(Codegen *g);
|
||||
ExprNode* semant(Environ* e);
|
||||
TNode* translate(Codegen* g);
|
||||
};
|
||||
|
||||
struct ObjectCastNode : public ExprNode {
|
||||
ExprNode *expr;
|
||||
string type_ident;
|
||||
ObjectCastNode(ExprNode *e, const string &t) :expr(e), type_ident(t) {}
|
||||
~ObjectCastNode() { delete expr; }
|
||||
ExprNode *semant(Environ *e);
|
||||
TNode *translate(Codegen *g);
|
||||
ExprNode* expr;
|
||||
string type_ident;
|
||||
ObjectCastNode(ExprNode* e, const string& t) : expr(e), type_ident(t) {}
|
||||
~ObjectCastNode()
|
||||
{
|
||||
delete expr;
|
||||
}
|
||||
ExprNode* semant(Environ* e);
|
||||
TNode* translate(Codegen* g);
|
||||
};
|
||||
|
||||
struct ObjectHandleNode : public ExprNode {
|
||||
ExprNode *expr;
|
||||
ObjectHandleNode(ExprNode *e) :expr(e) {}
|
||||
~ObjectHandleNode() { delete expr; }
|
||||
ExprNode *semant(Environ *e);
|
||||
TNode *translate(Codegen *g);
|
||||
ExprNode* expr;
|
||||
ObjectHandleNode(ExprNode* e) : expr(e) {}
|
||||
~ObjectHandleNode()
|
||||
{
|
||||
delete expr;
|
||||
}
|
||||
ExprNode* semant(Environ* e);
|
||||
TNode* translate(Codegen* g);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
+5
-5
@@ -2,12 +2,12 @@
|
||||
#ifndef LABEL_H
|
||||
#define LABEL_H
|
||||
|
||||
struct Label{
|
||||
string name; //name of label
|
||||
int def,ref; //pos of defn and goto/restore src
|
||||
int data_sz; //size of data at this label.
|
||||
struct Label {
|
||||
string name; //name of label
|
||||
int def, ref; //pos of defn and goto/restore src
|
||||
int data_sz; //size of data at this label.
|
||||
|
||||
Label( const string &n,int d,int r,int sz ):name(n),def(d),ref(r),data_sz(sz){}
|
||||
Label(const string& n, int d, int r, int sz) : name(n), def(d), ref(r), data_sz(sz) {}
|
||||
};
|
||||
|
||||
#endif
|
||||
+232
-161
@@ -1,63 +1,73 @@
|
||||
|
||||
#include "std.hpp"
|
||||
#include "nodes.hpp"
|
||||
#include "std.hpp"
|
||||
|
||||
set<string> Node::usedfuncs;
|
||||
|
||||
///////////////////////////////
|
||||
// generic exception thrower //
|
||||
///////////////////////////////
|
||||
void Node::ex(){
|
||||
ex( "INTERNAL COMPILER ERROR" );
|
||||
void Node::ex()
|
||||
{
|
||||
ex("INTERNAL COMPILER ERROR");
|
||||
}
|
||||
|
||||
void Node::ex( const string &e ){
|
||||
throw Ex( e,-1,"" );
|
||||
void Node::ex(const string& e)
|
||||
{
|
||||
throw Ex(e, -1, "");
|
||||
}
|
||||
|
||||
void Node::ex( const string &e,int pos ){
|
||||
throw Ex( e,pos,"" );
|
||||
void Node::ex(const string& e, int pos)
|
||||
{
|
||||
throw Ex(e, pos, "");
|
||||
}
|
||||
|
||||
void Node::ex( const string &e,int pos,const string &f ){
|
||||
throw Ex( e,pos,f );
|
||||
void Node::ex(const string& e, int pos, const string& f)
|
||||
{
|
||||
throw Ex(e, pos, f);
|
||||
}
|
||||
|
||||
///////////////////////////////
|
||||
// Generate a local variable //
|
||||
///////////////////////////////
|
||||
VarNode *Node::genLocal( Environ *e,Type *ty ){
|
||||
string t=genLabel();
|
||||
Decl *d=e->decls->insertDecl( t,ty,DECL_LOCAL );
|
||||
return new DeclVarNode( d );
|
||||
VarNode* Node::genLocal(Environ* e, Type* ty)
|
||||
{
|
||||
string t = genLabel();
|
||||
Decl* d = e->decls->insertDecl(t, ty, DECL_LOCAL);
|
||||
return new DeclVarNode(d);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////
|
||||
// if type is const, return const value else 0 //
|
||||
/////////////////////////////////////////////////
|
||||
ConstNode *Node::constValue( Type *ty ){
|
||||
ConstType *c=ty->constType();
|
||||
if( !c ) return 0;
|
||||
ty=c->valueType;
|
||||
if( ty==Type::int_type ) return new IntConstNode( c->intValue );
|
||||
if( ty==Type::float_type ) return new FloatConstNode( c->floatValue );
|
||||
return new StringConstNode( c->stringValue );
|
||||
ConstNode* Node::constValue(Type* ty)
|
||||
{
|
||||
ConstType* c = ty->constType();
|
||||
if (!c)
|
||||
return 0;
|
||||
ty = c->valueType;
|
||||
if (ty == Type::int_type)
|
||||
return new IntConstNode(c->intValue);
|
||||
if (ty == Type::float_type)
|
||||
return new FloatConstNode(c->floatValue);
|
||||
return new StringConstNode(c->stringValue);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
// work out var offsets - return size of local frame //
|
||||
///////////////////////////////////////////////////////
|
||||
int Node::enumVars( Environ *e ){
|
||||
int Node::enumVars(Environ* e)
|
||||
{
|
||||
//calc offsets
|
||||
int p_size=0,l_size=0;
|
||||
for( int k=0;k<e->decls->size();++k ){
|
||||
Decl *d=e->decls->decls[k];
|
||||
if( d->kind & DECL_PARAM ){
|
||||
d->offset=p_size+20;
|
||||
p_size+=4;
|
||||
}else if( d->kind & DECL_LOCAL ){
|
||||
d->offset=-4-l_size;
|
||||
l_size+=4;
|
||||
int p_size = 0, l_size = 0;
|
||||
for (int k = 0; k < e->decls->size(); ++k) {
|
||||
Decl* d = e->decls->decls[k];
|
||||
if (d->kind & DECL_PARAM) {
|
||||
d->offset = p_size + 20;
|
||||
p_size += 4;
|
||||
} else if (d->kind & DECL_LOCAL) {
|
||||
d->offset = -4 - l_size;
|
||||
l_size += 4;
|
||||
}
|
||||
}
|
||||
return l_size;
|
||||
@@ -66,30 +76,38 @@ int Node::enumVars( Environ *e ){
|
||||
//////////////////////////////
|
||||
// initialize all vars to 0 //
|
||||
//////////////////////////////
|
||||
TNode *Node::createVars( Environ *e ){
|
||||
int k;
|
||||
TNode *t=0;
|
||||
TNode* Node::createVars(Environ* e)
|
||||
{
|
||||
int k;
|
||||
TNode* t = 0;
|
||||
//initialize locals
|
||||
for( k=0;k<e->decls->size();++k ){
|
||||
Decl *d=e->decls->decls[k];
|
||||
if( d->kind!=DECL_LOCAL ) continue;
|
||||
if( d->type->vectorType() ) continue;
|
||||
if( !t ) t=new TNode( IR_CONST,0,0,0 );
|
||||
TNode *p=new TNode( IR_LOCAL,0,0,d->offset );
|
||||
p=new TNode( IR_MEM,p,0 );
|
||||
t=new TNode( IR_MOVE,t,p );
|
||||
for (k = 0; k < e->decls->size(); ++k) {
|
||||
Decl* d = e->decls->decls[k];
|
||||
if (d->kind != DECL_LOCAL)
|
||||
continue;
|
||||
if (d->type->vectorType())
|
||||
continue;
|
||||
if (!t)
|
||||
t = new TNode(IR_CONST, 0, 0, 0);
|
||||
TNode* p = new TNode(IR_LOCAL, 0, 0, d->offset);
|
||||
p = new TNode(IR_MEM, p, 0);
|
||||
t = new TNode(IR_MOVE, t, p);
|
||||
}
|
||||
//initialize vectors
|
||||
for( k=0;k<e->decls->size();++k ){
|
||||
Decl *d=e->decls->decls[k];
|
||||
if( d->kind==DECL_PARAM ) continue;
|
||||
VectorType *v=d->type->vectorType();
|
||||
if( !v ) continue;
|
||||
TNode *p=call( "__bbVecAlloc",global( v->label ) );
|
||||
TNode *m=d->kind==DECL_GLOBAL ? global( "_v"+d->name ) : local( d->offset );
|
||||
p=move( p,mem( m ) );
|
||||
if( t ) t=seq( t,p );
|
||||
else t=p;
|
||||
for (k = 0; k < e->decls->size(); ++k) {
|
||||
Decl* d = e->decls->decls[k];
|
||||
if (d->kind == DECL_PARAM)
|
||||
continue;
|
||||
VectorType* v = d->type->vectorType();
|
||||
if (!v)
|
||||
continue;
|
||||
TNode* p = call("__bbVecAlloc", global(v->label));
|
||||
TNode* m = d->kind == DECL_GLOBAL ? global("_v" + d->name) : local(d->offset);
|
||||
p = move(p, mem(m));
|
||||
if (t)
|
||||
t = seq(t, p);
|
||||
else
|
||||
t = p;
|
||||
}
|
||||
return t;
|
||||
}
|
||||
@@ -97,35 +115,37 @@ TNode *Node::createVars( Environ *e ){
|
||||
////////////////////////
|
||||
// release local vars //
|
||||
////////////////////////
|
||||
TNode *Node::deleteVars( Environ *e ){
|
||||
TNode *t=0,*l=0,*p,*p1 = nullptr,*p2 = nullptr;
|
||||
for( int k=0;k<e->decls->size();++k ){
|
||||
Decl *d=e->decls->decls[k];
|
||||
Type *type=d->type;
|
||||
TNode* Node::deleteVars(Environ* e)
|
||||
{
|
||||
TNode *t = 0, *l = 0, *p, *p1 = nullptr, *p2 = nullptr;
|
||||
for (int k = 0; k < e->decls->size(); ++k) {
|
||||
Decl* d = e->decls->decls[k];
|
||||
Type* type = d->type;
|
||||
string func;
|
||||
if( type==Type::string_type ){
|
||||
if( d->kind==DECL_LOCAL || d->kind==DECL_PARAM ){
|
||||
func="__bbStrRelease";
|
||||
p1=mem( local( d->offset ) );
|
||||
p2=0;
|
||||
if (type == Type::string_type) {
|
||||
if (d->kind == DECL_LOCAL || d->kind == DECL_PARAM) {
|
||||
func = "__bbStrRelease";
|
||||
p1 = mem(local(d->offset));
|
||||
p2 = 0;
|
||||
}
|
||||
}else if( type->structType() ){
|
||||
if( d->kind==DECL_LOCAL ){
|
||||
func="__bbObjRelease";
|
||||
p1=mem( local( d->offset ) );
|
||||
p2=0;
|
||||
} else if (type->structType()) {
|
||||
if (d->kind == DECL_LOCAL) {
|
||||
func = "__bbObjRelease";
|
||||
p1 = mem(local(d->offset));
|
||||
p2 = 0;
|
||||
}
|
||||
}else if( VectorType *v=type->vectorType() ){
|
||||
if( d->kind==DECL_LOCAL ){
|
||||
func="__bbVecFree";
|
||||
p1=mem( local( d->offset ) );
|
||||
p2=global( v->label );
|
||||
} else if (VectorType* v = type->vectorType()) {
|
||||
if (d->kind == DECL_LOCAL) {
|
||||
func = "__bbVecFree";
|
||||
p1 = mem(local(d->offset));
|
||||
p2 = global(v->label);
|
||||
}
|
||||
}
|
||||
if( !func.size() ) continue;
|
||||
p=new TNode( IR_SEQ,call( func,p1,p2 ),0 );
|
||||
(l ? l->r : t)=p;
|
||||
l=p;
|
||||
if (!func.size())
|
||||
continue;
|
||||
p = new TNode(IR_SEQ, call(func, p1, p2), 0);
|
||||
(l ? l->r : t) = p;
|
||||
l = p;
|
||||
}
|
||||
return t;
|
||||
}
|
||||
@@ -133,152 +153,203 @@ TNode *Node::deleteVars( Environ *e ){
|
||||
//////////////////////////////////////////////////////////////
|
||||
// compare 2 translated operands - return 1 if true, else 0 //
|
||||
//////////////////////////////////////////////////////////////
|
||||
TNode *Node::compare( int op,TNode *l,TNode *r,Type *ty ){
|
||||
int n=0;
|
||||
if( ty==Type::float_type ){
|
||||
switch( op ){
|
||||
case '=':n=IR_FSETEQ;break;case NE :n=IR_FSETNE;break;
|
||||
case '<':n=IR_FSETLT;break;case '>':n=IR_FSETGT;break;
|
||||
case LE :n=IR_FSETLE;break;case GE :n=IR_FSETGE;break;
|
||||
TNode* Node::compare(int op, TNode* l, TNode* r, Type* ty)
|
||||
{
|
||||
int n = 0;
|
||||
if (ty == Type::float_type) {
|
||||
switch (op) {
|
||||
case '=':
|
||||
n = IR_FSETEQ;
|
||||
break;
|
||||
case NE:
|
||||
n = IR_FSETNE;
|
||||
break;
|
||||
case '<':
|
||||
n = IR_FSETLT;
|
||||
break;
|
||||
case '>':
|
||||
n = IR_FSETGT;
|
||||
break;
|
||||
case LE:
|
||||
n = IR_FSETLE;
|
||||
break;
|
||||
case GE:
|
||||
n = IR_FSETGE;
|
||||
break;
|
||||
}
|
||||
}else{
|
||||
switch( op ){
|
||||
case '=':n=IR_SETEQ;break;case NE :n=IR_SETNE;break;
|
||||
case '<':n=IR_SETLT;break;case '>':n=IR_SETGT;break;
|
||||
case LE :n=IR_SETLE;break;case GE :n=IR_SETGE;break;
|
||||
} else {
|
||||
switch (op) {
|
||||
case '=':
|
||||
n = IR_SETEQ;
|
||||
break;
|
||||
case NE:
|
||||
n = IR_SETNE;
|
||||
break;
|
||||
case '<':
|
||||
n = IR_SETLT;
|
||||
break;
|
||||
case '>':
|
||||
n = IR_SETGT;
|
||||
break;
|
||||
case LE:
|
||||
n = IR_SETLE;
|
||||
break;
|
||||
case GE:
|
||||
n = IR_SETGE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( ty==Type::string_type ){
|
||||
l=call( "__bbStrCompare",l,r );
|
||||
r=new TNode( IR_CONST,0,0,0 );
|
||||
}else if( ty->structType() ){
|
||||
l=call( "__bbObjCompare",l,r );
|
||||
r=new TNode( IR_CONST,0,0,0 );
|
||||
if (ty == Type::string_type) {
|
||||
l = call("__bbStrCompare", l, r);
|
||||
r = new TNode(IR_CONST, 0, 0, 0);
|
||||
} else if (ty->structType()) {
|
||||
l = call("__bbObjCompare", l, r);
|
||||
r = new TNode(IR_CONST, 0, 0, 0);
|
||||
}
|
||||
return new TNode( n,l,r );
|
||||
return new TNode(n, l, r);
|
||||
}
|
||||
|
||||
/////////////////////////////////
|
||||
// calculate the type of a tag //
|
||||
/////////////////////////////////
|
||||
Type *Node::tagType( const string &tag,Environ *e ){
|
||||
Type *t;
|
||||
if( tag.size() ){
|
||||
t=e->findType( tag );
|
||||
if( !t ) ex( "Type \""+tag+"\" not found" );
|
||||
}else t=0;
|
||||
Type* Node::tagType(const string& tag, Environ* e)
|
||||
{
|
||||
Type* t;
|
||||
if (tag.size()) {
|
||||
t = e->findType(tag);
|
||||
if (!t)
|
||||
ex("Type \"" + tag + "\" not found");
|
||||
} else
|
||||
t = 0;
|
||||
return t;
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
// Generate a fresh ASM label //
|
||||
////////////////////////////////
|
||||
string Node::genLabel(){
|
||||
string Node::genLabel()
|
||||
{
|
||||
static int cnt;
|
||||
return "_"+itoa( ++cnt & 0x7fffffff );
|
||||
return "_" + itoa(++cnt & 0x7fffffff);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////
|
||||
// create a stmt-type function call with int result //
|
||||
//////////////////////////////////////////////////////
|
||||
TNode *Node::call( const string &func,TNode *a0,TNode *a1,TNode *a2 ){
|
||||
int size=0;
|
||||
TNode *t=0;
|
||||
if( a0 ){
|
||||
t=move( a0,mem( arg(0) ) );
|
||||
size+=4;
|
||||
if( a1 ){
|
||||
t=seq( t,move( a1,mem( arg(4) ) ) );
|
||||
size+=4;
|
||||
if( a2 ){
|
||||
t=seq( t,move( a2,mem( arg(8) ) ) );
|
||||
size+=4;
|
||||
TNode* Node::call(const string& func, TNode* a0, TNode* a1, TNode* a2)
|
||||
{
|
||||
int size = 0;
|
||||
TNode* t = 0;
|
||||
if (a0) {
|
||||
t = move(a0, mem(arg(0)));
|
||||
size += 4;
|
||||
if (a1) {
|
||||
t = seq(t, move(a1, mem(arg(4))));
|
||||
size += 4;
|
||||
if (a2) {
|
||||
t = seq(t, move(a2, mem(arg(8))));
|
||||
size += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
TNode *l=new TNode( IR_GLOBAL,0,0,func );
|
||||
return new TNode( IR_CALL,l,t,size );
|
||||
TNode* l = new TNode(IR_GLOBAL, 0, 0, func);
|
||||
return new TNode(IR_CALL, l, t, size);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
// create a stmt-type function call with float result //
|
||||
////////////////////////////////////////////////////////
|
||||
TNode *Node::fcall( const string &func,TNode *a0,TNode *a1,TNode *a2 ){
|
||||
int size=0;
|
||||
TNode *t=0;
|
||||
if( a0 ){
|
||||
t=move( a0,mem( arg(0) ) );
|
||||
size+=4;
|
||||
if( a1 ){
|
||||
t=seq( t,move( a1,mem( arg(4) ) ) );
|
||||
size+=4;
|
||||
if( a2 ){
|
||||
t=seq( t,move( a2,mem( arg(8) ) ) );
|
||||
size+=4;
|
||||
TNode* Node::fcall(const string& func, TNode* a0, TNode* a1, TNode* a2)
|
||||
{
|
||||
int size = 0;
|
||||
TNode* t = 0;
|
||||
if (a0) {
|
||||
t = move(a0, mem(arg(0)));
|
||||
size += 4;
|
||||
if (a1) {
|
||||
t = seq(t, move(a1, mem(arg(4))));
|
||||
size += 4;
|
||||
if (a2) {
|
||||
t = seq(t, move(a2, mem(arg(8))));
|
||||
size += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
TNode *l=new TNode( IR_GLOBAL,0,0,func );
|
||||
return new TNode( IR_FCALL,l,t,size );
|
||||
TNode* l = new TNode(IR_GLOBAL, 0, 0, func);
|
||||
return new TNode(IR_FCALL, l, t, size);
|
||||
}
|
||||
|
||||
TNode *Node::seq( TNode *l,TNode *r ){
|
||||
return new TNode( IR_SEQ,l,r );
|
||||
TNode* Node::seq(TNode* l, TNode* r)
|
||||
{
|
||||
return new TNode(IR_SEQ, l, r);
|
||||
}
|
||||
|
||||
TNode *Node::move( TNode *src,TNode *dest ){
|
||||
return new TNode( IR_MOVE,src,dest );
|
||||
TNode* Node::move(TNode* src, TNode* dest)
|
||||
{
|
||||
return new TNode(IR_MOVE, src, dest);
|
||||
}
|
||||
|
||||
TNode *Node::global( const string &s ){
|
||||
return new TNode( IR_GLOBAL,0,0,s );
|
||||
TNode* Node::global(const string& s)
|
||||
{
|
||||
return new TNode(IR_GLOBAL, 0, 0, s);
|
||||
}
|
||||
|
||||
TNode *Node::local( int offset ){
|
||||
return new TNode( IR_LOCAL,0,0,offset );
|
||||
TNode* Node::local(int offset)
|
||||
{
|
||||
return new TNode(IR_LOCAL, 0, 0, offset);
|
||||
}
|
||||
|
||||
TNode *Node::arg( int offset ){
|
||||
return new TNode( IR_ARG,0,0,offset );
|
||||
TNode* Node::arg(int offset)
|
||||
{
|
||||
return new TNode(IR_ARG, 0, 0, offset);
|
||||
}
|
||||
|
||||
TNode *Node::mem( TNode *ref ){
|
||||
return new TNode( IR_MEM,ref,0 );
|
||||
TNode* Node::mem(TNode* ref)
|
||||
{
|
||||
return new TNode(IR_MEM, ref, 0);
|
||||
}
|
||||
|
||||
TNode *Node::add( TNode *l,TNode *r ){
|
||||
return new TNode( IR_ADD,l,r );
|
||||
TNode* Node::add(TNode* l, TNode* r)
|
||||
{
|
||||
return new TNode(IR_ADD, l, r);
|
||||
}
|
||||
|
||||
TNode *Node::mul( TNode *l,TNode *r ){
|
||||
return new TNode( IR_MUL,l,r );
|
||||
TNode* Node::mul(TNode* l, TNode* r)
|
||||
{
|
||||
return new TNode(IR_MUL, l, r);
|
||||
}
|
||||
|
||||
TNode *Node::iconst( int n ){
|
||||
return new TNode( IR_CONST,0,0,n );
|
||||
TNode* Node::iconst(int n)
|
||||
{
|
||||
return new TNode(IR_CONST, 0, 0, n);
|
||||
}
|
||||
|
||||
TNode *Node::ret(){
|
||||
return new TNode( IR_RET,0,0 );
|
||||
TNode* Node::ret()
|
||||
{
|
||||
return new TNode(IR_RET, 0, 0);
|
||||
}
|
||||
|
||||
TNode *Node::jsr( const string &s ){
|
||||
return new TNode( IR_JSR,0,0,s );
|
||||
TNode* Node::jsr(const string& s)
|
||||
{
|
||||
return new TNode(IR_JSR, 0, 0, s);
|
||||
}
|
||||
|
||||
TNode *Node::jump( const string &s ){
|
||||
return new TNode( IR_JUMP,0,0,s );
|
||||
TNode* Node::jump(const string& s)
|
||||
{
|
||||
return new TNode(IR_JUMP, 0, 0, s);
|
||||
}
|
||||
|
||||
TNode *Node::jumpt( TNode *expr,const string &s ){
|
||||
return new TNode( IR_JUMPT,expr,0,s );
|
||||
TNode* Node::jumpt(TNode* expr, const string& s)
|
||||
{
|
||||
return new TNode(IR_JUMPT, expr, 0, s);
|
||||
}
|
||||
|
||||
TNode *Node::jumpf( TNode *expr,const string &s ){
|
||||
return new TNode( IR_JUMPF,expr,0,s );
|
||||
TNode* Node::jumpf(TNode* expr, const string& s)
|
||||
{
|
||||
return new TNode(IR_JUMPF, expr, 0, s);
|
||||
}
|
||||
|
||||
TNode *Node::jumpge( TNode *l,TNode *r,const string &s ){
|
||||
return new TNode( IR_JUMPGE,l,r,s );
|
||||
TNode* Node::jumpge(TNode* l, TNode* r, const string& s)
|
||||
{
|
||||
return new TNode(IR_JUMPGE, l, r, s);
|
||||
}
|
||||
|
||||
|
||||
+32
-32
@@ -2,55 +2,55 @@
|
||||
#ifndef NODE_H
|
||||
#define NODE_H
|
||||
|
||||
#include "codegen.hpp"
|
||||
#include "environ.hpp"
|
||||
#include "ex.hpp"
|
||||
#include "toker.hpp"
|
||||
#include "environ.hpp"
|
||||
#include "codegen.hpp"
|
||||
|
||||
struct VarNode;
|
||||
struct ConstNode;
|
||||
|
||||
struct Node{
|
||||
virtual ~Node(){}
|
||||
struct Node {
|
||||
virtual ~Node() {}
|
||||
|
||||
//used user funcs...
|
||||
static set<string> usedfuncs;
|
||||
|
||||
//helper funcs
|
||||
static void ex();
|
||||
static void ex( const string &e );
|
||||
static void ex( const string &e,int pos );
|
||||
static void ex( const string &e,int pos,const string &f );
|
||||
static void ex(const string& e);
|
||||
static void ex(const string& e, int pos);
|
||||
static void ex(const string& e, int pos, const string& f);
|
||||
|
||||
static string genLabel();
|
||||
static VarNode *genLocal( Environ *e,Type *ty );
|
||||
static string genLabel();
|
||||
static VarNode* genLocal(Environ* e, Type* ty);
|
||||
|
||||
static TNode *compare( int op,TNode *l,TNode *r,Type *ty );
|
||||
static ConstNode *constValue( Type *ty );
|
||||
static TNode* compare(int op, TNode* l, TNode* r, Type* ty);
|
||||
static ConstNode* constValue(Type* ty);
|
||||
|
||||
static int enumVars( Environ *e );
|
||||
static Type *tagType( const string &s,Environ *e );
|
||||
static int enumVars(Environ* e);
|
||||
static Type* tagType(const string& s, Environ* e);
|
||||
|
||||
static TNode *createVars( Environ *e );
|
||||
static TNode *deleteVars( Environ *e );
|
||||
static TNode* createVars(Environ* e);
|
||||
static TNode* deleteVars(Environ* e);
|
||||
|
||||
static TNode *seq( TNode *l,TNode *r );
|
||||
static TNode *move( TNode *src,TNode *dest );
|
||||
static TNode *global( const string &s );
|
||||
static TNode *local( int offset );
|
||||
static TNode *arg( int offset );
|
||||
static TNode *mem( TNode *ref );
|
||||
static TNode *add( TNode *l,TNode *r );
|
||||
static TNode *mul( TNode *l,TNode *r );
|
||||
static TNode *iconst( int n );
|
||||
static TNode *ret();
|
||||
static TNode *jsr( const string &s );
|
||||
static TNode *jump( const string &s );
|
||||
static TNode *jumpt( TNode *cond,const string &s );
|
||||
static TNode *jumpf( TNode *cond,const string &s );
|
||||
static TNode *jumpge( TNode *l,TNode *r,const string &s );
|
||||
static TNode *call( const string &func,TNode *a0=0,TNode *a1=0,TNode *a2=0 );
|
||||
static TNode *fcall( const string &func,TNode *a0=0,TNode *a1=0,TNode *a2=0 );
|
||||
static TNode* seq(TNode* l, TNode* r);
|
||||
static TNode* move(TNode* src, TNode* dest);
|
||||
static TNode* global(const string& s);
|
||||
static TNode* local(int offset);
|
||||
static TNode* arg(int offset);
|
||||
static TNode* mem(TNode* ref);
|
||||
static TNode* add(TNode* l, TNode* r);
|
||||
static TNode* mul(TNode* l, TNode* r);
|
||||
static TNode* iconst(int n);
|
||||
static TNode* ret();
|
||||
static TNode* jsr(const string& s);
|
||||
static TNode* jump(const string& s);
|
||||
static TNode* jumpt(TNode* cond, const string& s);
|
||||
static TNode* jumpf(TNode* cond, const string& s);
|
||||
static TNode* jumpge(TNode* l, TNode* r, const string& s);
|
||||
static TNode* call(const string& func, TNode* a0 = 0, TNode* a1 = 0, TNode* a2 = 0);
|
||||
static TNode* fcall(const string& func, TNode* a0 = 0, TNode* a1 = 0, TNode* a2 = 0);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
+2
-2
@@ -2,9 +2,9 @@
|
||||
#ifndef NODES_H
|
||||
#define NODES_H
|
||||
|
||||
#include "exprnode.hpp"
|
||||
#include "stmtnode.hpp"
|
||||
#include "declnode.hpp"
|
||||
#include "exprnode.hpp"
|
||||
#include "prognode.hpp"
|
||||
#include "stmtnode.hpp"
|
||||
|
||||
#endif
|
||||
|
||||
+673
-530
File diff suppressed because it is too large
Load Diff
+37
-38
@@ -8,58 +8,57 @@
|
||||
#ifndef PARSER_H
|
||||
#define PARSER_H
|
||||
|
||||
#include "toker.hpp"
|
||||
#include "nodes.hpp"
|
||||
#include "toker.hpp"
|
||||
|
||||
class Parser{
|
||||
public:
|
||||
class Parser {
|
||||
public:
|
||||
Parser(Toker& t);
|
||||
|
||||
Parser( Toker &t );
|
||||
ProgNode* parse(const string& main);
|
||||
|
||||
ProgNode *parse( const string &main );
|
||||
private:
|
||||
string incfile;
|
||||
set<string> included;
|
||||
Toker * toker, *main_toker;
|
||||
map<string, DimNode*> arrayDecls;
|
||||
|
||||
private:
|
||||
string incfile;
|
||||
set<string> included;
|
||||
Toker *toker,*main_toker;
|
||||
map<string,DimNode*> arrayDecls;
|
||||
DeclSeqNode* consts;
|
||||
DeclSeqNode* structs;
|
||||
DeclSeqNode* funcs;
|
||||
DeclSeqNode* datas;
|
||||
|
||||
DeclSeqNode *consts;
|
||||
DeclSeqNode *structs;
|
||||
DeclSeqNode *funcs;
|
||||
DeclSeqNode *datas;
|
||||
StmtSeqNode* parseStmtSeq(int scope);
|
||||
void parseStmtSeq(StmtSeqNode* stmts, int scope);
|
||||
|
||||
StmtSeqNode *parseStmtSeq( int scope );
|
||||
void parseStmtSeq( StmtSeqNode *stmts,int scope );
|
||||
|
||||
void ex( const string &s );
|
||||
void exp( const string &s );
|
||||
void ex(const string& s);
|
||||
void exp(const string& s);
|
||||
|
||||
string parseIdent();
|
||||
void parseChar( int c );
|
||||
void parseChar(int c);
|
||||
string parseTypeTag();
|
||||
|
||||
VarNode *parseVar();
|
||||
VarNode *parseVar( const string &ident,const string &tag );
|
||||
CallNode *parseCall( const string &ident,const string &tag );
|
||||
IfNode *parseIf();
|
||||
VarNode* parseVar();
|
||||
VarNode* parseVar(const string& ident, const string& tag);
|
||||
CallNode* parseCall(const string& ident, const string& tag);
|
||||
IfNode* parseIf();
|
||||
|
||||
DeclNode *parseVarDecl( int kind,bool constant );
|
||||
DimNode *parseArrayDecl();
|
||||
DeclNode *parseFuncDecl();
|
||||
DeclNode *parseStructDecl();
|
||||
DeclNode* parseVarDecl(int kind, bool constant);
|
||||
DimNode* parseArrayDecl();
|
||||
DeclNode* parseFuncDecl();
|
||||
DeclNode* parseStructDecl();
|
||||
|
||||
ExprSeqNode *parseExprSeq();
|
||||
ExprSeqNode* parseExprSeq();
|
||||
|
||||
ExprNode *parseExpr( bool opt );
|
||||
ExprNode *parseExpr1( bool opt ); //And, Or, Eor
|
||||
ExprNode *parseExpr2( bool opt ); //<,=,>,<=,<>,>=
|
||||
ExprNode *parseExpr3( bool opt ); //+,-
|
||||
ExprNode *parseExpr4( bool opt ); //Lsr,Lsr,Asr
|
||||
ExprNode *parseExpr5( bool opt ); //*,/,Mod
|
||||
ExprNode *parseExpr6( bool opt ); //^
|
||||
ExprNode *parseUniExpr( bool opt ); //+,-,Not,~
|
||||
ExprNode *parsePrimary( bool opt );
|
||||
ExprNode* parseExpr(bool opt);
|
||||
ExprNode* parseExpr1(bool opt); //And, Or, Eor
|
||||
ExprNode* parseExpr2(bool opt); //<,=,>,<=,<>,>=
|
||||
ExprNode* parseExpr3(bool opt); //+,-
|
||||
ExprNode* parseExpr4(bool opt); //Lsr,Lsr,Asr
|
||||
ExprNode* parseExpr5(bool opt); //*,/,Mod
|
||||
ExprNode* parseExpr6(bool opt); //^
|
||||
ExprNode* parseUniExpr(bool opt); //+,-,Not,~
|
||||
ExprNode* parsePrimary(bool opt);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
+67
-63
@@ -1,136 +1,140 @@
|
||||
|
||||
#include "std.hpp"
|
||||
#include "nodes.hpp"
|
||||
#include "std.hpp"
|
||||
|
||||
//////////////////
|
||||
// The program! //
|
||||
//////////////////
|
||||
Environ *ProgNode::semant( Environ *e ){
|
||||
Environ* ProgNode::semant(Environ* e)
|
||||
{
|
||||
file_lab = genLabel();
|
||||
|
||||
file_lab=genLabel();
|
||||
StmtSeqNode::reset(stmts->file, file_lab);
|
||||
|
||||
StmtSeqNode::reset( stmts->file,file_lab );
|
||||
a_ptr<Environ> env(new Environ(genLabel(), Type::int_type, 0, e));
|
||||
|
||||
a_ptr<Environ> env( new Environ( genLabel(),Type::int_type,0,e ) );
|
||||
consts->proto(env->decls, env);
|
||||
structs->proto(env->typeDecls, env);
|
||||
structs->semant(env);
|
||||
funcs->proto(env->funcDecls, env);
|
||||
stmts->semant(env);
|
||||
funcs->semant(env);
|
||||
datas->proto(env->decls, env);
|
||||
datas->semant(env);
|
||||
|
||||
consts->proto( env->decls,env );
|
||||
structs->proto( env->typeDecls,env );
|
||||
structs->semant( env );
|
||||
funcs->proto( env->funcDecls,env );
|
||||
stmts->semant( env );
|
||||
funcs->semant( env );
|
||||
datas->proto( env->decls,env );
|
||||
datas->semant( env );
|
||||
|
||||
sem_env=env.release();
|
||||
sem_env = env.release();
|
||||
return sem_env;
|
||||
}
|
||||
|
||||
void ProgNode::translate( Codegen *g,const vector<UserFunc> &usrfuncs ){
|
||||
|
||||
void ProgNode::translate(Codegen* g, const vector<UserFunc>& usrfuncs)
|
||||
{
|
||||
int k;
|
||||
|
||||
if( g->debug ) g->s_data( stmts->file,file_lab );
|
||||
if (g->debug)
|
||||
g->s_data(stmts->file, file_lab);
|
||||
|
||||
//enumerate locals
|
||||
int size=enumVars( sem_env );
|
||||
int size = enumVars(sem_env);
|
||||
|
||||
//'Main' label
|
||||
g->enter( "__MAIN",size );
|
||||
g->enter("__MAIN", size);
|
||||
|
||||
//reset data pointer
|
||||
g->code( call( "__bbRestore",global( "__DATA" ) ) );
|
||||
g->code(call("__bbRestore", global("__DATA")));
|
||||
|
||||
//load external libs
|
||||
g->code( call( "__bbLoadLibs",global( "__LIBS" ) ) );
|
||||
g->code(call("__bbLoadLibs", global("__LIBS")));
|
||||
|
||||
//call main program
|
||||
g->code( jsr( sem_env->funcLabel+"_begin" ) );
|
||||
g->code( jump( sem_env->funcLabel+"_leave" ) );
|
||||
g->label( sem_env->funcLabel+"_begin" );
|
||||
g->code(jsr(sem_env->funcLabel + "_begin"));
|
||||
g->code(jump(sem_env->funcLabel + "_leave"));
|
||||
g->label(sem_env->funcLabel + "_begin");
|
||||
|
||||
//create locals
|
||||
TNode *t=createVars( sem_env );
|
||||
if( t ) g->code( t );
|
||||
if( g->debug ){
|
||||
string t=genLabel();
|
||||
g->s_data( "<main program>",t );
|
||||
g->code( call( "__bbDebugEnter",local(0),iconst((int)sem_env),global(t) ) );
|
||||
TNode* t = createVars(sem_env);
|
||||
if (t)
|
||||
g->code(t);
|
||||
if (g->debug) {
|
||||
string t = genLabel();
|
||||
g->s_data("<main program>", t);
|
||||
g->code(call("__bbDebugEnter", local(0), iconst((int)sem_env), global(t)));
|
||||
}
|
||||
|
||||
//no user funcs used!
|
||||
usedfuncs.clear();
|
||||
|
||||
//program statements
|
||||
stmts->translate( g );
|
||||
stmts->translate(g);
|
||||
|
||||
//emit return
|
||||
g->code( ret() );
|
||||
g->code(ret());
|
||||
|
||||
//check labels
|
||||
for( k=0;k<sem_env->labels.size();++k ){
|
||||
if( sem_env->labels[k]->def<0 ) ex( "Undefined label '"+sem_env->labels[k]->name+"'",sem_env->labels[k]->ref,stmts->file );
|
||||
for (k = 0; k < sem_env->labels.size(); ++k) {
|
||||
if (sem_env->labels[k]->def < 0)
|
||||
ex("Undefined label '" + sem_env->labels[k]->name + "'", sem_env->labels[k]->ref, stmts->file);
|
||||
}
|
||||
|
||||
//leave main program
|
||||
g->label( sem_env->funcLabel+"_leave" );
|
||||
t=deleteVars( sem_env );
|
||||
if( g->debug ) t=new TNode( IR_SEQ,call( "__bbDebugLeave" ),t );
|
||||
g->leave( t,0 );
|
||||
g->label(sem_env->funcLabel + "_leave");
|
||||
t = deleteVars(sem_env);
|
||||
if (g->debug)
|
||||
t = new TNode(IR_SEQ, call("__bbDebugLeave"), t);
|
||||
g->leave(t, 0);
|
||||
|
||||
//structs
|
||||
structs->translate( g );
|
||||
structs->translate(g);
|
||||
|
||||
//non-main functions
|
||||
funcs->translate( g );
|
||||
funcs->translate(g);
|
||||
|
||||
//data
|
||||
datas->translate( g );
|
||||
datas->translate(g);
|
||||
|
||||
//library functions
|
||||
map<string,vector<int> > libFuncs;
|
||||
map<string, vector<int>> libFuncs;
|
||||
|
||||
//lib ptrs
|
||||
g->flush();
|
||||
g->align_data(4);
|
||||
for( k=0;k<usrfuncs.size();++k ){
|
||||
const UserFunc &fn=usrfuncs[k];
|
||||
for (k = 0; k < usrfuncs.size(); ++k) {
|
||||
const UserFunc& fn = usrfuncs[k];
|
||||
|
||||
if( !usedfuncs.count(fn.ident) ) continue;
|
||||
if (!usedfuncs.count(fn.ident))
|
||||
continue;
|
||||
|
||||
libFuncs[fn.lib].push_back( k );
|
||||
libFuncs[fn.lib].push_back(k);
|
||||
|
||||
g->i_data( 0,"_f"+fn.ident );
|
||||
g->i_data(0, "_f" + fn.ident);
|
||||
}
|
||||
|
||||
//LIBS chunk
|
||||
g->flush();
|
||||
g->label( "__LIBS" );
|
||||
map<string,vector<int> >::const_iterator lf_it;
|
||||
for( lf_it=libFuncs.begin();lf_it!=libFuncs.end();++lf_it ){
|
||||
|
||||
g->label("__LIBS");
|
||||
map<string, vector<int>>::const_iterator lf_it;
|
||||
for (lf_it = libFuncs.begin(); lf_it != libFuncs.end(); ++lf_it) {
|
||||
//lib name
|
||||
g->s_data( lf_it->first );
|
||||
g->s_data(lf_it->first);
|
||||
|
||||
const vector<int> &fns=lf_it->second;
|
||||
const vector<int>& fns = lf_it->second;
|
||||
|
||||
for( int j=0;j<fns.size();++j ){
|
||||
const UserFunc &fn=usrfuncs[ fns[j] ];
|
||||
for (int j = 0; j < fns.size(); ++j) {
|
||||
const UserFunc& fn = usrfuncs[fns[j]];
|
||||
|
||||
//proc name
|
||||
g->s_data( fn.proc );
|
||||
g->s_data(fn.proc);
|
||||
|
||||
g->p_data( "_f"+fn.ident );
|
||||
g->p_data("_f" + fn.ident);
|
||||
}
|
||||
g->s_data( "" );
|
||||
g->s_data("");
|
||||
}
|
||||
g->s_data( "" );
|
||||
g->s_data("");
|
||||
|
||||
//DATA chunk
|
||||
g->flush();
|
||||
g->align_data( 4 );
|
||||
g->label( "__DATA" );
|
||||
datas->transdata( g );
|
||||
g->align_data(4);
|
||||
g->label("__DATA");
|
||||
datas->transdata(g);
|
||||
g->i_data(0);
|
||||
|
||||
//Thats IT!
|
||||
|
||||
+20
-18
@@ -2,38 +2,40 @@
|
||||
#ifndef PROGNODE_H
|
||||
#define PROGNODE_H
|
||||
|
||||
#include "node.hpp"
|
||||
#include "codegen.hpp"
|
||||
#include "node.hpp"
|
||||
|
||||
struct UserFunc{
|
||||
string ident,proc,lib;
|
||||
UserFunc( const UserFunc &t ):ident(t.ident),proc(t.proc),lib(t.lib){}
|
||||
UserFunc( const string &id,const string &pr,const string &lb ):ident(id),proc(pr),lib(lb){}
|
||||
struct UserFunc {
|
||||
string ident, proc, lib;
|
||||
UserFunc(const UserFunc& t) : ident(t.ident), proc(t.proc), lib(t.lib) {}
|
||||
UserFunc(const string& id, const string& pr, const string& lb) : ident(id), proc(pr), lib(lb) {}
|
||||
};
|
||||
|
||||
struct ProgNode : public Node{
|
||||
struct ProgNode : public Node {
|
||||
DeclSeqNode* consts;
|
||||
DeclSeqNode* structs;
|
||||
DeclSeqNode* funcs;
|
||||
DeclSeqNode* datas;
|
||||
StmtSeqNode* stmts;
|
||||
|
||||
DeclSeqNode *consts;
|
||||
DeclSeqNode *structs;
|
||||
DeclSeqNode *funcs;
|
||||
DeclSeqNode *datas;
|
||||
StmtSeqNode *stmts;
|
||||
|
||||
Environ *sem_env;
|
||||
Environ* sem_env;
|
||||
|
||||
string file_lab;
|
||||
|
||||
ProgNode( DeclSeqNode *c,DeclSeqNode *s,DeclSeqNode *f,DeclSeqNode *d,StmtSeqNode *ss ):consts(c),structs(s),funcs(f),datas(d),stmts(ss){}
|
||||
~ProgNode(){
|
||||
ProgNode(DeclSeqNode* c, DeclSeqNode* s, DeclSeqNode* f, DeclSeqNode* d, StmtSeqNode* ss)
|
||||
: consts(c), structs(s), funcs(f), datas(d), stmts(ss)
|
||||
{}
|
||||
~ProgNode()
|
||||
{
|
||||
delete consts;
|
||||
delete structs;
|
||||
delete funcs;
|
||||
delete datas;
|
||||
delete stmts;
|
||||
delete stmts;
|
||||
}
|
||||
|
||||
Environ *semant( Environ *e );
|
||||
void translate( Codegen *g,const vector<UserFunc> &userfuncs );
|
||||
Environ* semant(Environ* e);
|
||||
void translate(Codegen* g, const vector<UserFunc>& userfuncs);
|
||||
};
|
||||
|
||||
#endif
|
||||
+5
-5
@@ -5,14 +5,14 @@
|
||||
#include "config.hpp"
|
||||
#include "stdutil.hpp"
|
||||
|
||||
#include <set>
|
||||
#include <map>
|
||||
#include <fstream>
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
||||
+262
-166
@@ -1,18 +1,20 @@
|
||||
|
||||
#include "std.hpp"
|
||||
#include "nodes.hpp"
|
||||
#include "std.hpp"
|
||||
|
||||
static string fileLabel;
|
||||
static string fileLabel;
|
||||
static map<string, string> fileMap;
|
||||
|
||||
void StmtNode::debug(int pos, Codegen *g) {
|
||||
void StmtNode::debug(int pos, Codegen* g)
|
||||
{
|
||||
if (g->debug) {
|
||||
TNode *t = fileLabel.size() ? global(fileLabel) : iconst(0);
|
||||
TNode* t = fileLabel.size() ? global(fileLabel) : iconst(0);
|
||||
g->code(call("__bbDebugStmt", iconst(pos), t));
|
||||
}
|
||||
}
|
||||
|
||||
void StmtSeqNode::reset(const string &file, const string &lab) {
|
||||
void StmtSeqNode::reset(const string& file, const string& lab)
|
||||
{
|
||||
fileLabel = "";
|
||||
fileMap.clear();
|
||||
|
||||
@@ -22,28 +24,35 @@ void StmtSeqNode::reset(const string &file, const string &lab) {
|
||||
////////////////////////
|
||||
// Statement Sequence //
|
||||
////////////////////////
|
||||
void StmtSeqNode::semant(Environ *e) {
|
||||
void StmtSeqNode::semant(Environ* e)
|
||||
{
|
||||
for (int k = 0; k < stmts.size(); ++k) {
|
||||
try { stmts[k]->semant(e); } catch (Ex &x) {
|
||||
if (x.pos < 0) x.pos = stmts[k]->pos;
|
||||
if (!x.file.size()) x.file = file;
|
||||
try {
|
||||
stmts[k]->semant(e);
|
||||
} catch (Ex& x) {
|
||||
if (x.pos < 0)
|
||||
x.pos = stmts[k]->pos;
|
||||
if (!x.file.size())
|
||||
x.file = file;
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void StmtSeqNode::translate(Codegen *g) {
|
||||
|
||||
string t = fileLabel;
|
||||
void StmtSeqNode::translate(Codegen* g)
|
||||
{
|
||||
string t = fileLabel;
|
||||
fileLabel = file.size() ? fileMap[file] : "";
|
||||
for (int k = 0; k < stmts.size(); ++k) {
|
||||
StmtNode *stmt = stmts[k];
|
||||
StmtNode* stmt = stmts[k];
|
||||
stmt->debug(stmts[k]->pos, g);
|
||||
try {
|
||||
stmt->translate(g);
|
||||
} catch (Ex &x) {
|
||||
if (x.pos < 0) x.pos = stmts[k]->pos;
|
||||
if (!x.file.size()) x.file = file;
|
||||
} catch (Ex& x) {
|
||||
if (x.pos < 0)
|
||||
x.pos = stmts[k]->pos;
|
||||
if (!x.file.size())
|
||||
x.file = file;
|
||||
throw;
|
||||
}
|
||||
}
|
||||
@@ -53,17 +62,18 @@ void StmtSeqNode::translate(Codegen *g) {
|
||||
/////////////////
|
||||
// An Include! //
|
||||
/////////////////
|
||||
void IncludeNode::semant(Environ *e) {
|
||||
|
||||
label = genLabel();
|
||||
void IncludeNode::semant(Environ* e)
|
||||
{
|
||||
label = genLabel();
|
||||
fileMap[file] = label;
|
||||
|
||||
stmts->semant(e);
|
||||
}
|
||||
|
||||
void IncludeNode::translate(Codegen *g) {
|
||||
|
||||
if (g->debug) g->s_data(file, label);
|
||||
void IncludeNode::translate(Codegen* g)
|
||||
{
|
||||
if (g->debug)
|
||||
g->s_data(file, label);
|
||||
|
||||
stmts->translate(g);
|
||||
}
|
||||
@@ -71,29 +81,35 @@ void IncludeNode::translate(Codegen *g) {
|
||||
///////////////////
|
||||
// a declaration //
|
||||
///////////////////
|
||||
void DeclStmtNode::semant(Environ *e) {
|
||||
void DeclStmtNode::semant(Environ* e)
|
||||
{
|
||||
decl->proto(e->decls, e);
|
||||
decl->semant(e);
|
||||
}
|
||||
|
||||
void DeclStmtNode::translate(Codegen *g) {
|
||||
void DeclStmtNode::translate(Codegen* g)
|
||||
{
|
||||
decl->translate(g);
|
||||
}
|
||||
|
||||
//////////////////////////////
|
||||
// Dim AND declare an Array //
|
||||
//////////////////////////////
|
||||
void DimNode::semant(Environ *e) {
|
||||
Type *t = tagType(tag, e);
|
||||
if (Decl *d = e->findDecl(ident)) {
|
||||
ArrayType *a = d->type->arrayType();
|
||||
void DimNode::semant(Environ* e)
|
||||
{
|
||||
Type* t = tagType(tag, e);
|
||||
if (Decl* d = e->findDecl(ident)) {
|
||||
ArrayType* a = d->type->arrayType();
|
||||
if (!a || a->dims != exprs->size() || (t && a->elementType != t)) {
|
||||
ex("Duplicate identifier");
|
||||
}
|
||||
sem_type = a; sem_decl = 0;
|
||||
sem_type = a;
|
||||
sem_decl = 0;
|
||||
} else {
|
||||
if (e->level > 0) ex("Array not found in main program");
|
||||
if (!t) t = Type::int_type;
|
||||
if (e->level > 0)
|
||||
ex("Array not found in main program");
|
||||
if (!t)
|
||||
t = Type::int_type;
|
||||
sem_type = new ArrayType(t, exprs->size());
|
||||
sem_decl = e->decls->insertDecl(ident, sem_type, DECL_ARRAY);
|
||||
e->types.push_back(sem_type);
|
||||
@@ -102,8 +118,9 @@ void DimNode::semant(Environ *e) {
|
||||
exprs->castTo(Type::int_type, e);
|
||||
}
|
||||
|
||||
void DimNode::translate(Codegen *g) {
|
||||
TNode *t;
|
||||
void DimNode::translate(Codegen* g)
|
||||
{
|
||||
TNode* t;
|
||||
g->code(call("__bbUndimArray", global("_a" + ident)));
|
||||
for (int k = 0; k < exprs->size(); ++k) {
|
||||
t = add(global("_a" + ident), iconst(k * 4 + 12));
|
||||
@@ -112,125 +129,160 @@ void DimNode::translate(Codegen *g) {
|
||||
}
|
||||
g->code(call("__bbDimArray", global("_a" + ident)));
|
||||
|
||||
if (!sem_decl) return;
|
||||
if (!sem_decl)
|
||||
return;
|
||||
|
||||
int et, k;
|
||||
Type *ty = sem_type->arrayType()->elementType;
|
||||
if (ty == Type::int_type) et = 1;
|
||||
else if (ty == Type::float_type) et = 2;
|
||||
else if (ty == Type::string_type) et = 3;
|
||||
else et = 5;
|
||||
int et, k;
|
||||
Type* ty = sem_type->arrayType()->elementType;
|
||||
if (ty == Type::int_type)
|
||||
et = 1;
|
||||
else if (ty == Type::float_type)
|
||||
et = 2;
|
||||
else if (ty == Type::string_type)
|
||||
et = 3;
|
||||
else
|
||||
et = 5;
|
||||
|
||||
g->align_data(4);
|
||||
g->i_data(0, "_a" + ident);
|
||||
g->i_data(et);
|
||||
g->i_data(exprs->size());
|
||||
for (k = 0; k < exprs->size(); ++k) g->i_data(0);
|
||||
for (k = 0; k < exprs->size(); ++k)
|
||||
g->i_data(0);
|
||||
}
|
||||
|
||||
////////////////
|
||||
// Assignment //
|
||||
////////////////
|
||||
void AssNode::semant(Environ *e) {
|
||||
void AssNode::semant(Environ* e)
|
||||
{
|
||||
var->semant(e);
|
||||
if (var->sem_type->constType()) ex("Constants can not be assigned to");
|
||||
if (var->sem_type->vectorType()) ex("Blitz arrays can not be assigned to");
|
||||
if (var->sem_type->constType())
|
||||
ex("Constants can not be assigned to");
|
||||
if (var->sem_type->vectorType())
|
||||
ex("Blitz arrays can not be assigned to");
|
||||
expr = expr->semant(e);
|
||||
expr = expr->castTo(var->sem_type, e);
|
||||
}
|
||||
|
||||
void AssNode::translate(Codegen *g) {
|
||||
void AssNode::translate(Codegen* g)
|
||||
{
|
||||
g->code(var->store(g, expr->translate(g)));
|
||||
}
|
||||
|
||||
//////////////////////////
|
||||
// Expression statement //
|
||||
//////////////////////////
|
||||
void ExprStmtNode::semant(Environ *e) {
|
||||
void ExprStmtNode::semant(Environ* e)
|
||||
{
|
||||
expr = expr->semant(e);
|
||||
}
|
||||
|
||||
void ExprStmtNode::translate(Codegen *g) {
|
||||
TNode *t = expr->translate(g);
|
||||
if (expr->sem_type == Type::string_type) t = call("__bbStrRelease", t);
|
||||
void ExprStmtNode::translate(Codegen* g)
|
||||
{
|
||||
TNode* t = expr->translate(g);
|
||||
if (expr->sem_type == Type::string_type)
|
||||
t = call("__bbStrRelease", t);
|
||||
g->code(t);
|
||||
}
|
||||
|
||||
////////////////
|
||||
// user label //
|
||||
////////////////
|
||||
void LabelNode::semant(Environ *e) {
|
||||
if (Label *l = e->findLabel(ident)) {
|
||||
if (l->def >= 0) ex("duplicate label");
|
||||
l->def = pos; l->data_sz = data_sz;
|
||||
} else e->insertLabel(ident, pos, -1, data_sz);
|
||||
void LabelNode::semant(Environ* e)
|
||||
{
|
||||
if (Label* l = e->findLabel(ident)) {
|
||||
if (l->def >= 0)
|
||||
ex("duplicate label");
|
||||
l->def = pos;
|
||||
l->data_sz = data_sz;
|
||||
} else
|
||||
e->insertLabel(ident, pos, -1, data_sz);
|
||||
ident = e->funcLabel + ident;
|
||||
}
|
||||
|
||||
void LabelNode::translate(Codegen *g) {
|
||||
void LabelNode::translate(Codegen* g)
|
||||
{
|
||||
g->label("_l" + ident);
|
||||
}
|
||||
|
||||
//////////////////
|
||||
// Restore data //
|
||||
//////////////////
|
||||
void RestoreNode::semant(Environ *e) {
|
||||
if (e->level > 0) e = e->globals;
|
||||
void RestoreNode::semant(Environ* e)
|
||||
{
|
||||
if (e->level > 0)
|
||||
e = e->globals;
|
||||
|
||||
if (ident.size() == 0) sem_label = 0;
|
||||
if (ident.size() == 0)
|
||||
sem_label = 0;
|
||||
else {
|
||||
sem_label = e->findLabel(ident);
|
||||
if (!sem_label) sem_label = e->insertLabel(ident, -1, pos, -1);
|
||||
if (!sem_label)
|
||||
sem_label = e->insertLabel(ident, -1, pos, -1);
|
||||
}
|
||||
}
|
||||
|
||||
void RestoreNode::translate(Codegen *g) {
|
||||
TNode *t = global("__DATA");
|
||||
if (sem_label) t = add(t, iconst(sem_label->data_sz * 8));
|
||||
void RestoreNode::translate(Codegen* g)
|
||||
{
|
||||
TNode* t = global("__DATA");
|
||||
if (sem_label)
|
||||
t = add(t, iconst(sem_label->data_sz * 8));
|
||||
g->code(call("__bbRestore", t));
|
||||
}
|
||||
|
||||
////////////////////
|
||||
// Goto statement //
|
||||
////////////////////
|
||||
void GotoNode::semant(Environ *e) {
|
||||
void GotoNode::semant(Environ* e)
|
||||
{
|
||||
if (!e->findLabel(ident)) {
|
||||
e->insertLabel(ident, -1, pos, -1);
|
||||
}
|
||||
ident = e->funcLabel + ident;
|
||||
}
|
||||
|
||||
void GotoNode::translate(Codegen *g) {
|
||||
void GotoNode::translate(Codegen* g)
|
||||
{
|
||||
g->code(jump("_l" + ident));
|
||||
}
|
||||
|
||||
/////////////////////
|
||||
// Gosub statement //
|
||||
/////////////////////
|
||||
void GosubNode::semant(Environ *e) {
|
||||
if (e->level > 0) ex("'Gosub' may not be used inside a function");
|
||||
if (!e->findLabel(ident)) e->insertLabel(ident, -1, pos, -1);
|
||||
void GosubNode::semant(Environ* e)
|
||||
{
|
||||
if (e->level > 0)
|
||||
ex("'Gosub' may not be used inside a function");
|
||||
if (!e->findLabel(ident))
|
||||
e->insertLabel(ident, -1, pos, -1);
|
||||
ident = e->funcLabel + ident;
|
||||
}
|
||||
|
||||
void GosubNode::translate(Codegen *g) {
|
||||
void GosubNode::translate(Codegen* g)
|
||||
{
|
||||
g->code(jsr("_l" + ident));
|
||||
}
|
||||
|
||||
//////////////////
|
||||
// If statement //
|
||||
//////////////////
|
||||
void IfNode::semant(Environ *e) {
|
||||
void IfNode::semant(Environ* e)
|
||||
{
|
||||
expr = expr->semant(e);
|
||||
expr = expr->castTo(Type::int_type, e);
|
||||
stmts->semant(e);
|
||||
if (elseOpt) elseOpt->semant(e);
|
||||
if (elseOpt)
|
||||
elseOpt->semant(e);
|
||||
}
|
||||
|
||||
void IfNode::translate(Codegen *g) {
|
||||
if (ConstNode *c = expr->constNode()) {
|
||||
if (c->intValue()) stmts->translate(g);
|
||||
else if (elseOpt) elseOpt->translate(g);
|
||||
void IfNode::translate(Codegen* g)
|
||||
{
|
||||
if (ConstNode* c = expr->constNode()) {
|
||||
if (c->intValue())
|
||||
stmts->translate(g);
|
||||
else if (elseOpt)
|
||||
elseOpt->translate(g);
|
||||
} else {
|
||||
string _else = genLabel();
|
||||
g->code(jumpf(expr->translate(g), _else));
|
||||
@@ -249,30 +301,36 @@ void IfNode::translate(Codegen *g) {
|
||||
///////////
|
||||
// Break //
|
||||
///////////
|
||||
void ExitNode::semant(Environ *e) {
|
||||
void ExitNode::semant(Environ* e)
|
||||
{
|
||||
sem_brk = e->breakLabel;
|
||||
if (!sem_brk.size()) ex("break must appear inside a loop");
|
||||
if (!sem_brk.size())
|
||||
ex("break must appear inside a loop");
|
||||
}
|
||||
|
||||
void ExitNode::translate(Codegen *g) {
|
||||
void ExitNode::translate(Codegen* g)
|
||||
{
|
||||
g->code(new TNode(IR_JUMP, 0, 0, sem_brk));
|
||||
}
|
||||
|
||||
/////////////////////
|
||||
// While statement //
|
||||
/////////////////////
|
||||
void WhileNode::semant(Environ *e) {
|
||||
expr = expr->semant(e);
|
||||
expr = expr->castTo(Type::int_type, e);
|
||||
void WhileNode::semant(Environ* e)
|
||||
{
|
||||
expr = expr->semant(e);
|
||||
expr = expr->castTo(Type::int_type, e);
|
||||
string brk = e->setBreak(sem_brk = genLabel());
|
||||
stmts->semant(e);
|
||||
e->setBreak(brk);
|
||||
}
|
||||
|
||||
void WhileNode::translate(Codegen *g) {
|
||||
void WhileNode::translate(Codegen* g)
|
||||
{
|
||||
string loop = genLabel();
|
||||
if (ConstNode *c = expr->constNode()) {
|
||||
if (!c->intValue()) return;
|
||||
if (ConstNode* c = expr->constNode()) {
|
||||
if (!c->intValue())
|
||||
return;
|
||||
g->label(loop);
|
||||
stmts->translate(g);
|
||||
g->code(jump(loop));
|
||||
@@ -291,11 +349,12 @@ void WhileNode::translate(Codegen *g) {
|
||||
///////////////////
|
||||
// For/Next loop //
|
||||
///////////////////
|
||||
ForNode::ForNode(VarNode *var, ExprNode *from, ExprNode *to, ExprNode *step, StmtSeqNode *ss, int np)
|
||||
:var(var), fromExpr(from), toExpr(to), stepExpr(step), stmts(ss), nextPos(np) {
|
||||
}
|
||||
ForNode::ForNode(VarNode* var, ExprNode* from, ExprNode* to, ExprNode* step, StmtSeqNode* ss, int np)
|
||||
: var(var), fromExpr(from), toExpr(to), stepExpr(step), stmts(ss), nextPos(np)
|
||||
{}
|
||||
|
||||
ForNode::~ForNode() {
|
||||
ForNode::~ForNode()
|
||||
{
|
||||
delete stmts;
|
||||
delete stepExpr;
|
||||
delete toExpr;
|
||||
@@ -303,30 +362,34 @@ ForNode::~ForNode() {
|
||||
delete var;
|
||||
}
|
||||
|
||||
void ForNode::semant(Environ *e) {
|
||||
void ForNode::semant(Environ* e)
|
||||
{
|
||||
var->semant(e);
|
||||
Type *ty = var->sem_type;
|
||||
if (ty->constType()) ex("Index variable can not be constant");
|
||||
Type* ty = var->sem_type;
|
||||
if (ty->constType())
|
||||
ex("Index variable can not be constant");
|
||||
if (ty != Type::int_type && ty != Type::float_type) {
|
||||
ex("index variable must be integer or real");
|
||||
}
|
||||
fromExpr = fromExpr->semant(e);
|
||||
fromExpr = fromExpr->castTo(ty, e);
|
||||
toExpr = toExpr->semant(e);
|
||||
toExpr = toExpr->castTo(ty, e);
|
||||
toExpr = toExpr->semant(e);
|
||||
toExpr = toExpr->castTo(ty, e);
|
||||
stepExpr = stepExpr->semant(e);
|
||||
stepExpr = stepExpr->castTo(ty, e);
|
||||
|
||||
if (!stepExpr->constNode()) ex("Step value must be constant");
|
||||
if (!stepExpr->constNode())
|
||||
ex("Step value must be constant");
|
||||
|
||||
string brk = e->setBreak(sem_brk = genLabel());
|
||||
stmts->semant(e);
|
||||
e->setBreak(brk);
|
||||
}
|
||||
|
||||
void ForNode::translate(Codegen *g) {
|
||||
|
||||
TNode *t; Type *ty = var->sem_type;
|
||||
void ForNode::translate(Codegen* g)
|
||||
{
|
||||
TNode* t;
|
||||
Type* ty = var->sem_type;
|
||||
|
||||
//initial assignment
|
||||
g->code(var->store(g, fromExpr->translate(g)));
|
||||
@@ -340,13 +403,13 @@ void ForNode::translate(Codegen *g) {
|
||||
//execute the step part
|
||||
debug(nextPos, g);
|
||||
int op = ty == Type::int_type ? IR_ADD : IR_FADD;
|
||||
t = new TNode(op, var->load(g), stepExpr->translate(g));
|
||||
t = new TNode(op, var->load(g), stepExpr->translate(g));
|
||||
g->code(var->store(g, t));
|
||||
|
||||
//test for loop cond
|
||||
g->label(cond);
|
||||
op = stepExpr->constNode()->floatValue() > 0 ? '>' : '<';
|
||||
t = compare(op, var->load(g), toExpr->translate(g), ty);
|
||||
t = compare(op, var->load(g), toExpr->translate(g), ty);
|
||||
g->code(jumpf(t, loop));
|
||||
|
||||
g->label(sem_brk);
|
||||
@@ -355,21 +418,26 @@ void ForNode::translate(Codegen *g) {
|
||||
///////////////////////////////
|
||||
// For each object of a type //
|
||||
///////////////////////////////
|
||||
void ForEachNode::semant(Environ *e) {
|
||||
void ForEachNode::semant(Environ* e)
|
||||
{
|
||||
var->semant(e);
|
||||
Type *ty = var->sem_type;
|
||||
Type* ty = var->sem_type;
|
||||
|
||||
if (ty->structType() == 0) ex("Index variable is not a NewType");
|
||||
Type *t = e->findType(typeIdent);
|
||||
if (!t) ex("Type name not found");
|
||||
if (t != ty) ex("Type mismatch");
|
||||
if (ty->structType() == 0)
|
||||
ex("Index variable is not a NewType");
|
||||
Type* t = e->findType(typeIdent);
|
||||
if (!t)
|
||||
ex("Type name not found");
|
||||
if (t != ty)
|
||||
ex("Type mismatch");
|
||||
|
||||
string brk = e->setBreak(sem_brk = genLabel());
|
||||
stmts->semant(e);
|
||||
e->setBreak(brk);
|
||||
}
|
||||
|
||||
void ForEachNode::translate(Codegen *g) {
|
||||
void ForEachNode::translate(Codegen* g)
|
||||
{
|
||||
TNode *t, *l, *r;
|
||||
string _loop = genLabel();
|
||||
|
||||
@@ -377,10 +445,10 @@ void ForEachNode::translate(Codegen *g) {
|
||||
|
||||
if (var->isObjParam()) {
|
||||
objFirst = "__bbObjEachFirst2";
|
||||
objNext = "__bbObjEachNext2";
|
||||
objNext = "__bbObjEachNext2";
|
||||
} else {
|
||||
objFirst = "__bbObjEachFirst";
|
||||
objNext = "__bbObjEachNext";
|
||||
objNext = "__bbObjEachNext";
|
||||
}
|
||||
|
||||
l = var->translate(g);
|
||||
@@ -401,7 +469,8 @@ void ForEachNode::translate(Codegen *g) {
|
||||
////////////////////////////
|
||||
// Return from a function //
|
||||
////////////////////////////
|
||||
void ReturnNode::semant(Environ *e) {
|
||||
void ReturnNode::semant(Environ* e)
|
||||
{
|
||||
if (e->level <= 0 && expr) {
|
||||
ex("Main program cannot return a value");
|
||||
}
|
||||
@@ -417,19 +486,20 @@ void ReturnNode::semant(Environ *e) {
|
||||
expr = new IntConstNode(0);
|
||||
}
|
||||
}
|
||||
expr = expr->semant(e);
|
||||
expr = expr->castTo(e->returnType, e);
|
||||
expr = expr->semant(e);
|
||||
expr = expr->castTo(e->returnType, e);
|
||||
returnLabel = e->funcLabel + "_leave";
|
||||
}
|
||||
}
|
||||
|
||||
void ReturnNode::translate(Codegen *g) {
|
||||
void ReturnNode::translate(Codegen* g)
|
||||
{
|
||||
if (!expr) {
|
||||
g->code(new TNode(IR_RET, 0, 0));
|
||||
return;
|
||||
}
|
||||
|
||||
TNode *t = expr->translate(g);
|
||||
TNode* t = expr->translate(g);
|
||||
|
||||
if (expr->sem_type == Type::float_type) {
|
||||
g->code(new TNode(IR_FRETURN, t, 0, returnLabel));
|
||||
@@ -441,45 +511,57 @@ void ReturnNode::translate(Codegen *g) {
|
||||
//////////////////////
|
||||
// Delete statement //
|
||||
//////////////////////
|
||||
void DeleteNode::semant(Environ *e) {
|
||||
void DeleteNode::semant(Environ* e)
|
||||
{
|
||||
expr = expr->semant(e);
|
||||
if (expr->sem_type->structType() == 0) ex("Can't delete non-Newtype");
|
||||
if (expr->sem_type->structType() == 0)
|
||||
ex("Can't delete non-Newtype");
|
||||
}
|
||||
|
||||
void DeleteNode::translate(Codegen *g) {
|
||||
TNode *t = expr->translate(g);
|
||||
void DeleteNode::translate(Codegen* g)
|
||||
{
|
||||
TNode* t = expr->translate(g);
|
||||
g->code(call("__bbObjDelete", t));
|
||||
}
|
||||
|
||||
///////////////////////////
|
||||
// Delete each of a type //
|
||||
///////////////////////////
|
||||
void DeleteEachNode::semant(Environ *e) {
|
||||
Type *t = e->findType(typeIdent);
|
||||
if (!t || t->structType() == 0) ex("Specified name is not a NewType name");
|
||||
void DeleteEachNode::semant(Environ* e)
|
||||
{
|
||||
Type* t = e->findType(typeIdent);
|
||||
if (!t || t->structType() == 0)
|
||||
ex("Specified name is not a NewType name");
|
||||
}
|
||||
|
||||
void DeleteEachNode::translate(Codegen *g) {
|
||||
void DeleteEachNode::translate(Codegen* g)
|
||||
{
|
||||
g->code(call("__bbObjDeleteEach", global("_t" + typeIdent)));
|
||||
}
|
||||
|
||||
///////////////////////////
|
||||
// Insert object in list //
|
||||
///////////////////////////
|
||||
void InsertNode::semant(Environ *e) {
|
||||
expr1 = expr1->semant(e);
|
||||
expr2 = expr2->semant(e);
|
||||
StructType *t1 = expr1->sem_type->structType();
|
||||
StructType *t2 = expr2->sem_type->structType();
|
||||
if (!t1 || !t2) ex("Illegal expression type");
|
||||
if (t1 != t2) ex("Objects types are differnt");
|
||||
void InsertNode::semant(Environ* e)
|
||||
{
|
||||
expr1 = expr1->semant(e);
|
||||
expr2 = expr2->semant(e);
|
||||
StructType* t1 = expr1->sem_type->structType();
|
||||
StructType* t2 = expr2->sem_type->structType();
|
||||
if (!t1 || !t2)
|
||||
ex("Illegal expression type");
|
||||
if (t1 != t2)
|
||||
ex("Objects types are differnt");
|
||||
}
|
||||
|
||||
void InsertNode::translate(Codegen *g) {
|
||||
TNode *t1 = expr1->translate(g);
|
||||
if (g->debug) t1 = jumpf(t1, "__bbNullObjEx");
|
||||
TNode *t2 = expr2->translate(g);
|
||||
if (g->debug) t2 = jumpf(t2, "__bbNullObjEx");
|
||||
void InsertNode::translate(Codegen* g)
|
||||
{
|
||||
TNode* t1 = expr1->translate(g);
|
||||
if (g->debug)
|
||||
t1 = jumpf(t1, "__bbNullObjEx");
|
||||
TNode* t2 = expr2->translate(g);
|
||||
if (g->debug)
|
||||
t2 = jumpf(t2, "__bbNullObjEx");
|
||||
string s = before ? "__bbObjInsBefore" : "__bbObjInsAfter";
|
||||
g->code(call(s, t1, t2));
|
||||
}
|
||||
@@ -487,47 +569,51 @@ void InsertNode::translate(Codegen *g) {
|
||||
////////////////////////
|
||||
// A select statement //
|
||||
////////////////////////
|
||||
void SelectNode::semant(Environ *e) {
|
||||
expr = expr->semant(e);
|
||||
Type *ty = expr->sem_type;
|
||||
if (ty->structType()) ex("Select cannot be used with objects");
|
||||
void SelectNode::semant(Environ* e)
|
||||
{
|
||||
expr = expr->semant(e);
|
||||
Type* ty = expr->sem_type;
|
||||
if (ty->structType())
|
||||
ex("Select cannot be used with objects");
|
||||
|
||||
//we need a temp var
|
||||
Decl *d = e->decls->insertDecl(genLabel(), expr->sem_type, DECL_LOCAL);
|
||||
Decl* d = e->decls->insertDecl(genLabel(), expr->sem_type, DECL_LOCAL);
|
||||
sem_temp = new DeclVarNode(d);
|
||||
|
||||
for (int k = 0; k < cases.size(); ++k) {
|
||||
CaseNode *c = cases[k];
|
||||
CaseNode* c = cases[k];
|
||||
c->exprs->semant(e);
|
||||
c->exprs->castTo(ty, e);
|
||||
c->stmts->semant(e);
|
||||
}
|
||||
if (defStmts) defStmts->semant(e);
|
||||
if (defStmts)
|
||||
defStmts->semant(e);
|
||||
}
|
||||
|
||||
void SelectNode::translate(Codegen *g) {
|
||||
|
||||
Type *ty = expr->sem_type;
|
||||
int k;
|
||||
void SelectNode::translate(Codegen* g)
|
||||
{
|
||||
Type* ty = expr->sem_type;
|
||||
int k;
|
||||
|
||||
g->code(sem_temp->store(g, expr->translate(g)));
|
||||
|
||||
vector<string> labs;
|
||||
string brk = genLabel();
|
||||
string brk = genLabel();
|
||||
|
||||
for (k = 0; k < cases.size(); ++k) {
|
||||
CaseNode *c = cases[k];
|
||||
CaseNode* c = cases[k];
|
||||
labs.push_back(genLabel());
|
||||
for (int j = 0; j < c->exprs->size(); ++j) {
|
||||
ExprNode *e = c->exprs->exprs[j];
|
||||
TNode *t = compare('=', sem_temp->load(g), e->translate(g), ty);
|
||||
ExprNode* e = c->exprs->exprs[j];
|
||||
TNode* t = compare('=', sem_temp->load(g), e->translate(g), ty);
|
||||
g->code(jumpt(t, labs.back()));
|
||||
}
|
||||
}
|
||||
if (defStmts) defStmts->translate(g);
|
||||
if (defStmts)
|
||||
defStmts->translate(g);
|
||||
g->code(jump(brk));
|
||||
for (k = 0; k < cases.size(); ++k) {
|
||||
CaseNode *c = cases[k];
|
||||
CaseNode* c = cases[k];
|
||||
g->label(labs[k]);
|
||||
c->stmts->translate(g);
|
||||
g->code(jump(brk));
|
||||
@@ -539,8 +625,9 @@ void SelectNode::translate(Codegen *g) {
|
||||
////////////////////////////
|
||||
// Repeat...Until/Forever //
|
||||
////////////////////////////
|
||||
void RepeatNode::semant(Environ *e) {
|
||||
sem_brk = genLabel();
|
||||
void RepeatNode::semant(Environ* e)
|
||||
{
|
||||
sem_brk = genLabel();
|
||||
string brk = e->setBreak(sem_brk);
|
||||
stmts->semant(e);
|
||||
e->setBreak(brk);
|
||||
@@ -550,18 +637,21 @@ void RepeatNode::semant(Environ *e) {
|
||||
}
|
||||
}
|
||||
|
||||
void RepeatNode::translate(Codegen *g) {
|
||||
|
||||
void RepeatNode::translate(Codegen* g)
|
||||
{
|
||||
string loop = genLabel();
|
||||
g->label(loop);
|
||||
stmts->translate(g);
|
||||
debug(untilPos, g);
|
||||
|
||||
if (ConstNode *c = expr ? expr->constNode() : 0) {
|
||||
if (!c->intValue()) g->code(jump(loop));
|
||||
if (ConstNode* c = expr ? expr->constNode() : 0) {
|
||||
if (!c->intValue())
|
||||
g->code(jump(loop));
|
||||
} else {
|
||||
if (expr) g->code(jumpf(expr->translate(g), loop));
|
||||
else g->code(jump(loop));
|
||||
if (expr)
|
||||
g->code(jumpf(expr->translate(g), loop));
|
||||
else
|
||||
g->code(jump(loop));
|
||||
}
|
||||
g->label(sem_brk);
|
||||
}
|
||||
@@ -569,17 +659,23 @@ void RepeatNode::translate(Codegen *g) {
|
||||
///////////////
|
||||
// Read data //
|
||||
///////////////
|
||||
void ReadNode::semant(Environ *e) {
|
||||
void ReadNode::semant(Environ* e)
|
||||
{
|
||||
var->semant(e);
|
||||
if (var->sem_type->constType()) ex("Constants can not be modified");
|
||||
if (var->sem_type->structType()) ex("Data can not be read into an object");
|
||||
if (var->sem_type->constType())
|
||||
ex("Constants can not be modified");
|
||||
if (var->sem_type->structType())
|
||||
ex("Data can not be read into an object");
|
||||
}
|
||||
|
||||
void ReadNode::translate(Codegen *g) {
|
||||
TNode *t;
|
||||
if (var->sem_type == Type::int_type) t = call("__bbReadInt");
|
||||
else if (var->sem_type == Type::float_type) t = fcall("__bbReadFloat");
|
||||
else t = call("__bbReadStr");
|
||||
void ReadNode::translate(Codegen* g)
|
||||
{
|
||||
TNode* t;
|
||||
if (var->sem_type == Type::int_type)
|
||||
t = call("__bbReadInt");
|
||||
else if (var->sem_type == Type::float_type)
|
||||
t = fcall("__bbReadFloat");
|
||||
else
|
||||
t = call("__bbReadStr");
|
||||
g->code(var->store(g, t));
|
||||
}
|
||||
|
||||
|
||||
+239
-166
@@ -4,226 +4,299 @@
|
||||
|
||||
#include "node.hpp"
|
||||
|
||||
struct StmtNode : public Node{
|
||||
int pos; //offset in source stream
|
||||
StmtNode():pos(-1){}
|
||||
void debug( int pos,Codegen *g );
|
||||
struct StmtNode : public Node {
|
||||
int pos; //offset in source stream
|
||||
StmtNode() : pos(-1) {}
|
||||
void debug(int pos, Codegen* g);
|
||||
|
||||
virtual void semant( Environ *e ){}
|
||||
virtual void translate( Codegen *g ){}
|
||||
virtual void semant(Environ* e) {}
|
||||
virtual void translate(Codegen* g) {}
|
||||
};
|
||||
|
||||
struct StmtSeqNode : public Node{
|
||||
string file;
|
||||
struct StmtSeqNode : public Node {
|
||||
string file;
|
||||
vector<StmtNode*> stmts;
|
||||
StmtSeqNode( const string &f ):file(f){}
|
||||
~StmtSeqNode(){ for( ;stmts.size();stmts.pop_back() ) delete stmts.back(); }
|
||||
void semant( Environ *e );
|
||||
void translate( Codegen *g );
|
||||
void push_back( StmtNode *s ){ stmts.push_back( s ); }
|
||||
int size(){ return stmts.size(); }
|
||||
StmtSeqNode(const string& f) : file(f) {}
|
||||
~StmtSeqNode()
|
||||
{
|
||||
for (; stmts.size(); stmts.pop_back())
|
||||
delete stmts.back();
|
||||
}
|
||||
void semant(Environ* e);
|
||||
void translate(Codegen* g);
|
||||
void push_back(StmtNode* s)
|
||||
{
|
||||
stmts.push_back(s);
|
||||
}
|
||||
int size()
|
||||
{
|
||||
return stmts.size();
|
||||
}
|
||||
|
||||
static void reset( const string &file,const string &lab );
|
||||
static void reset(const string& file, const string& lab);
|
||||
};
|
||||
|
||||
#include "exprnode.hpp"
|
||||
#include "declnode.hpp"
|
||||
#include "exprnode.hpp"
|
||||
|
||||
struct IncludeNode : public StmtNode{
|
||||
string file,label;
|
||||
StmtSeqNode *stmts;
|
||||
IncludeNode( const string &t,StmtSeqNode *ss ):file(t),stmts(ss){}
|
||||
~IncludeNode(){ delete stmts; }
|
||||
struct IncludeNode : public StmtNode {
|
||||
string file, label;
|
||||
StmtSeqNode* stmts;
|
||||
IncludeNode(const string& t, StmtSeqNode* ss) : file(t), stmts(ss) {}
|
||||
~IncludeNode()
|
||||
{
|
||||
delete stmts;
|
||||
}
|
||||
|
||||
void semant( Environ *e );
|
||||
void translate( Codegen *g );
|
||||
void semant(Environ* e);
|
||||
void translate(Codegen* g);
|
||||
};
|
||||
|
||||
struct DeclStmtNode : public StmtNode{
|
||||
DeclNode *decl;
|
||||
DeclStmtNode( DeclNode *d ):decl(d){ pos=d->pos; }
|
||||
~DeclStmtNode(){ delete decl; }
|
||||
void semant( Environ *e );
|
||||
void translate( Codegen *g );
|
||||
struct DeclStmtNode : public StmtNode {
|
||||
DeclNode* decl;
|
||||
DeclStmtNode(DeclNode* d) : decl(d)
|
||||
{
|
||||
pos = d->pos;
|
||||
}
|
||||
~DeclStmtNode()
|
||||
{
|
||||
delete decl;
|
||||
}
|
||||
void semant(Environ* e);
|
||||
void translate(Codegen* g);
|
||||
};
|
||||
|
||||
struct DimNode : public StmtNode{
|
||||
string ident,tag;
|
||||
ExprSeqNode *exprs;
|
||||
ArrayType *sem_type;
|
||||
Decl *sem_decl;
|
||||
DimNode( const string &i,const string &t,ExprSeqNode *e ):ident(i),tag(t),exprs(e){}
|
||||
~DimNode(){ delete exprs; }
|
||||
void semant( Environ *e );
|
||||
void translate( Codegen *g );
|
||||
struct DimNode : public StmtNode {
|
||||
string ident, tag;
|
||||
ExprSeqNode* exprs;
|
||||
ArrayType* sem_type;
|
||||
Decl* sem_decl;
|
||||
DimNode(const string& i, const string& t, ExprSeqNode* e) : ident(i), tag(t), exprs(e) {}
|
||||
~DimNode()
|
||||
{
|
||||
delete exprs;
|
||||
}
|
||||
void semant(Environ* e);
|
||||
void translate(Codegen* g);
|
||||
};
|
||||
|
||||
struct AssNode : public StmtNode{
|
||||
VarNode *var;
|
||||
ExprNode *expr;
|
||||
AssNode( VarNode *var,ExprNode *expr ):var(var),expr(expr){}
|
||||
~AssNode(){ delete var;delete expr; }
|
||||
void semant( Environ *e );
|
||||
void translate( Codegen *g );
|
||||
struct AssNode : public StmtNode {
|
||||
VarNode* var;
|
||||
ExprNode* expr;
|
||||
AssNode(VarNode* var, ExprNode* expr) : var(var), expr(expr) {}
|
||||
~AssNode()
|
||||
{
|
||||
delete var;
|
||||
delete expr;
|
||||
}
|
||||
void semant(Environ* e);
|
||||
void translate(Codegen* g);
|
||||
};
|
||||
|
||||
struct ExprStmtNode : public StmtNode{
|
||||
ExprNode *expr;
|
||||
ExprStmtNode( ExprNode *e ):expr(e){}
|
||||
~ExprStmtNode(){ delete expr; }
|
||||
void semant( Environ *e );
|
||||
void translate( Codegen *g );
|
||||
struct ExprStmtNode : public StmtNode {
|
||||
ExprNode* expr;
|
||||
ExprStmtNode(ExprNode* e) : expr(e) {}
|
||||
~ExprStmtNode()
|
||||
{
|
||||
delete expr;
|
||||
}
|
||||
void semant(Environ* e);
|
||||
void translate(Codegen* g);
|
||||
};
|
||||
|
||||
struct LabelNode : public StmtNode{
|
||||
struct LabelNode : public StmtNode {
|
||||
string ident;
|
||||
int data_sz;
|
||||
LabelNode( const string &s,int sz ):ident(s),data_sz(sz){}
|
||||
void semant( Environ *e );
|
||||
void translate( Codegen *g );
|
||||
int data_sz;
|
||||
LabelNode(const string& s, int sz) : ident(s), data_sz(sz) {}
|
||||
void semant(Environ* e);
|
||||
void translate(Codegen* g);
|
||||
};
|
||||
|
||||
struct GotoNode : public StmtNode{
|
||||
struct GotoNode : public StmtNode {
|
||||
string ident;
|
||||
GotoNode( const string &s ):ident(s){}
|
||||
void semant( Environ *e );
|
||||
void translate( Codegen *g );
|
||||
GotoNode(const string& s) : ident(s) {}
|
||||
void semant(Environ* e);
|
||||
void translate(Codegen* g);
|
||||
};
|
||||
|
||||
struct GosubNode : public StmtNode{
|
||||
struct GosubNode : public StmtNode {
|
||||
string ident;
|
||||
GosubNode( const string &s ):ident(s){}
|
||||
void semant( Environ *e );
|
||||
void translate( Codegen *g );
|
||||
GosubNode(const string& s) : ident(s) {}
|
||||
void semant(Environ* e);
|
||||
void translate(Codegen* g);
|
||||
};
|
||||
|
||||
struct IfNode : public StmtNode{
|
||||
ExprNode *expr;
|
||||
StmtSeqNode *stmts,*elseOpt;
|
||||
IfNode( ExprNode *e,StmtSeqNode *s,StmtSeqNode *o ):expr(e),stmts(s),elseOpt(o){}
|
||||
~IfNode(){ delete expr;delete stmts;delete elseOpt; }
|
||||
void semant( Environ *e );
|
||||
void translate( Codegen *g );
|
||||
struct IfNode : public StmtNode {
|
||||
ExprNode* expr;
|
||||
StmtSeqNode *stmts, *elseOpt;
|
||||
IfNode(ExprNode* e, StmtSeqNode* s, StmtSeqNode* o) : expr(e), stmts(s), elseOpt(o) {}
|
||||
~IfNode()
|
||||
{
|
||||
delete expr;
|
||||
delete stmts;
|
||||
delete elseOpt;
|
||||
}
|
||||
void semant(Environ* e);
|
||||
void translate(Codegen* g);
|
||||
};
|
||||
|
||||
struct ExitNode : public StmtNode{
|
||||
struct ExitNode : public StmtNode {
|
||||
string sem_brk;
|
||||
void semant( Environ *e );
|
||||
void translate( Codegen *g );
|
||||
void semant(Environ* e);
|
||||
void translate(Codegen* g);
|
||||
};
|
||||
|
||||
struct WhileNode : public StmtNode{
|
||||
int wendPos;
|
||||
ExprNode *expr;
|
||||
StmtSeqNode *stmts;
|
||||
string sem_brk;
|
||||
WhileNode( ExprNode *e,StmtSeqNode *s,int wp ):expr(e),stmts(s),wendPos(wp){}
|
||||
~WhileNode(){ delete expr;delete stmts; }
|
||||
void semant( Environ *e );
|
||||
void translate( Codegen *g );
|
||||
struct WhileNode : public StmtNode {
|
||||
int wendPos;
|
||||
ExprNode* expr;
|
||||
StmtSeqNode* stmts;
|
||||
string sem_brk;
|
||||
WhileNode(ExprNode* e, StmtSeqNode* s, int wp) : expr(e), stmts(s), wendPos(wp) {}
|
||||
~WhileNode()
|
||||
{
|
||||
delete expr;
|
||||
delete stmts;
|
||||
}
|
||||
void semant(Environ* e);
|
||||
void translate(Codegen* g);
|
||||
};
|
||||
|
||||
struct ForNode : public StmtNode{
|
||||
int nextPos;
|
||||
VarNode *var;
|
||||
ExprNode *fromExpr,*toExpr,*stepExpr;
|
||||
StmtSeqNode *stmts;
|
||||
string sem_brk;
|
||||
ForNode( VarNode *v,ExprNode *f,ExprNode *t,ExprNode *s,StmtSeqNode *ss,int np );
|
||||
struct ForNode : public StmtNode {
|
||||
int nextPos;
|
||||
VarNode* var;
|
||||
ExprNode * fromExpr, *toExpr, *stepExpr;
|
||||
StmtSeqNode* stmts;
|
||||
string sem_brk;
|
||||
ForNode(VarNode* v, ExprNode* f, ExprNode* t, ExprNode* s, StmtSeqNode* ss, int np);
|
||||
~ForNode();
|
||||
void semant( Environ *e );
|
||||
void translate( Codegen *g );
|
||||
void semant(Environ* e);
|
||||
void translate(Codegen* g);
|
||||
};
|
||||
|
||||
struct ForEachNode : public StmtNode{
|
||||
int nextPos;
|
||||
VarNode *var;
|
||||
struct ForEachNode : public StmtNode {
|
||||
int nextPos;
|
||||
VarNode* var;
|
||||
string typeIdent;
|
||||
StmtSeqNode* stmts;
|
||||
string sem_brk;
|
||||
ForEachNode(VarNode* v, const string& t, StmtSeqNode* s, int np) : var(v), typeIdent(t), stmts(s), nextPos(np) {}
|
||||
~ForEachNode()
|
||||
{
|
||||
delete var;
|
||||
delete stmts;
|
||||
}
|
||||
void semant(Environ* e);
|
||||
void translate(Codegen* g);
|
||||
};
|
||||
|
||||
struct ReturnNode : public StmtNode {
|
||||
ExprNode* expr;
|
||||
string returnLabel;
|
||||
ReturnNode(ExprNode* e) : expr(e) {}
|
||||
~ReturnNode()
|
||||
{
|
||||
delete expr;
|
||||
}
|
||||
void semant(Environ* e);
|
||||
void translate(Codegen* g);
|
||||
};
|
||||
|
||||
struct DeleteNode : public StmtNode {
|
||||
ExprNode* expr;
|
||||
DeleteNode(ExprNode* e) : expr(e) {}
|
||||
~DeleteNode()
|
||||
{
|
||||
delete expr;
|
||||
}
|
||||
void semant(Environ* e);
|
||||
void translate(Codegen* g);
|
||||
};
|
||||
|
||||
struct DeleteEachNode : public StmtNode {
|
||||
string typeIdent;
|
||||
StmtSeqNode *stmts;
|
||||
string sem_brk;
|
||||
ForEachNode( VarNode *v,const string &t,StmtSeqNode *s,int np):var(v),typeIdent(t),stmts(s),nextPos(np){}
|
||||
~ForEachNode(){ delete var;delete stmts; }
|
||||
void semant( Environ *e );
|
||||
void translate( Codegen *g );
|
||||
DeleteEachNode(const string& t) : typeIdent(t) {}
|
||||
void semant(Environ* e);
|
||||
void translate(Codegen* g);
|
||||
};
|
||||
|
||||
struct ReturnNode : public StmtNode{
|
||||
ExprNode *expr;
|
||||
string returnLabel;
|
||||
ReturnNode( ExprNode *e ):expr( e ){}
|
||||
~ReturnNode(){ delete expr; }
|
||||
void semant( Environ *e );
|
||||
void translate( Codegen *g );
|
||||
struct InsertNode : public StmtNode {
|
||||
ExprNode *expr1, *expr2;
|
||||
bool before;
|
||||
InsertNode(ExprNode* e1, ExprNode* e2, bool b) : expr1(e1), expr2(e2), before(b) {}
|
||||
~InsertNode()
|
||||
{
|
||||
delete expr1;
|
||||
delete expr2;
|
||||
}
|
||||
void semant(Environ* e);
|
||||
void translate(Codegen* g);
|
||||
};
|
||||
|
||||
struct DeleteNode : public StmtNode{
|
||||
ExprNode *expr;
|
||||
DeleteNode( ExprNode *e ):expr(e){}
|
||||
~DeleteNode(){ delete expr; }
|
||||
void semant( Environ *e );
|
||||
void translate( Codegen *g );
|
||||
struct CaseNode : public Node {
|
||||
ExprSeqNode* exprs;
|
||||
StmtSeqNode* stmts;
|
||||
CaseNode(ExprSeqNode* e, StmtSeqNode* s) : exprs(e), stmts(s) {}
|
||||
~CaseNode()
|
||||
{
|
||||
delete exprs;
|
||||
delete stmts;
|
||||
}
|
||||
};
|
||||
|
||||
struct DeleteEachNode : public StmtNode{
|
||||
string typeIdent;
|
||||
DeleteEachNode( const string &t ):typeIdent(t){}
|
||||
void semant( Environ *e );
|
||||
void translate( Codegen *g );
|
||||
};
|
||||
|
||||
struct InsertNode : public StmtNode{
|
||||
ExprNode *expr1,*expr2;
|
||||
bool before;
|
||||
InsertNode( ExprNode *e1,ExprNode *e2,bool b ):expr1(e1),expr2(e2),before(b){}
|
||||
~InsertNode(){ delete expr1;delete expr2; }
|
||||
void semant( Environ *e );
|
||||
void translate( Codegen *g );
|
||||
};
|
||||
|
||||
struct CaseNode : public Node{
|
||||
ExprSeqNode *exprs;
|
||||
StmtSeqNode *stmts;
|
||||
CaseNode( ExprSeqNode *e,StmtSeqNode *s ):exprs(e),stmts(s){}
|
||||
~CaseNode(){ delete exprs;delete stmts; }
|
||||
};
|
||||
|
||||
struct SelectNode : public StmtNode{
|
||||
ExprNode *expr;
|
||||
StmtSeqNode *defStmts;
|
||||
struct SelectNode : public StmtNode {
|
||||
ExprNode* expr;
|
||||
StmtSeqNode* defStmts;
|
||||
vector<CaseNode*> cases;
|
||||
VarNode *sem_temp;
|
||||
SelectNode( ExprNode *e ):expr(e),defStmts(0),sem_temp(0){}
|
||||
~SelectNode(){ delete expr;delete defStmts;delete sem_temp;for( ;cases.size();cases.pop_back() ) delete cases.back(); }
|
||||
void push_back( CaseNode *c ){ cases.push_back( c ); }
|
||||
void semant( Environ *e );
|
||||
void translate( Codegen *g );
|
||||
VarNode* sem_temp;
|
||||
SelectNode(ExprNode* e) : expr(e), defStmts(0), sem_temp(0) {}
|
||||
~SelectNode()
|
||||
{
|
||||
delete expr;
|
||||
delete defStmts;
|
||||
delete sem_temp;
|
||||
for (; cases.size(); cases.pop_back())
|
||||
delete cases.back();
|
||||
}
|
||||
void push_back(CaseNode* c)
|
||||
{
|
||||
cases.push_back(c);
|
||||
}
|
||||
void semant(Environ* e);
|
||||
void translate(Codegen* g);
|
||||
};
|
||||
|
||||
struct RepeatNode : public StmtNode{
|
||||
int untilPos;
|
||||
StmtSeqNode *stmts;
|
||||
ExprNode *expr;
|
||||
string sem_brk;
|
||||
RepeatNode( StmtSeqNode *s,ExprNode *e,int up ):stmts(s),expr(e),untilPos(up){}
|
||||
~RepeatNode(){ delete stmts;delete expr; }
|
||||
void semant( Environ *e );
|
||||
void translate( Codegen *g );
|
||||
struct RepeatNode : public StmtNode {
|
||||
int untilPos;
|
||||
StmtSeqNode* stmts;
|
||||
ExprNode* expr;
|
||||
string sem_brk;
|
||||
RepeatNode(StmtSeqNode* s, ExprNode* e, int up) : stmts(s), expr(e), untilPos(up) {}
|
||||
~RepeatNode()
|
||||
{
|
||||
delete stmts;
|
||||
delete expr;
|
||||
}
|
||||
void semant(Environ* e);
|
||||
void translate(Codegen* g);
|
||||
};
|
||||
|
||||
struct ReadNode : public StmtNode{
|
||||
VarNode *var;
|
||||
ReadNode( VarNode *v ):var(v){}
|
||||
~ReadNode(){ delete var; }
|
||||
void semant( Environ *e );
|
||||
void translate( Codegen *g );
|
||||
struct ReadNode : public StmtNode {
|
||||
VarNode* var;
|
||||
ReadNode(VarNode* v) : var(v) {}
|
||||
~ReadNode()
|
||||
{
|
||||
delete var;
|
||||
}
|
||||
void semant(Environ* e);
|
||||
void translate(Codegen* g);
|
||||
};
|
||||
|
||||
struct RestoreNode : public StmtNode{
|
||||
struct RestoreNode : public StmtNode {
|
||||
string ident;
|
||||
Label *sem_label;
|
||||
RestoreNode( const string &i ):ident(i){}
|
||||
void semant( Environ *e );
|
||||
void translate( Codegen *g );
|
||||
Label* sem_label;
|
||||
RestoreNode(const string& i) : ident(i) {}
|
||||
void semant(Environ* e);
|
||||
void translate(Codegen* g);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
+170
-141
@@ -1,217 +1,246 @@
|
||||
|
||||
#include "std.hpp"
|
||||
#include <cctype>
|
||||
#include "toker.hpp"
|
||||
#include <cctype>
|
||||
#include "ex.hpp"
|
||||
#include "std.hpp"
|
||||
|
||||
int Toker::chars_toked;
|
||||
|
||||
static map<string,int> alphaTokes,lowerTokes;
|
||||
static map<string, int> alphaTokes, lowerTokes;
|
||||
|
||||
static void makeKeywords(){
|
||||
static void makeKeywords()
|
||||
{
|
||||
static bool made;
|
||||
if( made ) return;
|
||||
if (made)
|
||||
return;
|
||||
|
||||
alphaTokes["Dim"]=DIM;
|
||||
alphaTokes["Goto"]=GOTO;
|
||||
alphaTokes["Gosub"]=GOSUB;
|
||||
alphaTokes["Return"]=RETURN;
|
||||
alphaTokes["Exit"]=EXIT;
|
||||
alphaTokes["If"]=IF;
|
||||
alphaTokes["Then"]=THEN;
|
||||
alphaTokes["Else"]=ELSE;
|
||||
alphaTokes["EndIf"]=ENDIF;
|
||||
alphaTokes["End If"]=ENDIF;
|
||||
alphaTokes["ElseIf"]=ELSEIF;
|
||||
alphaTokes["Else If"]=ELSEIF;
|
||||
alphaTokes["While"]=WHILE;
|
||||
alphaTokes["Wend"]=WEND;
|
||||
alphaTokes["For"]=FOR;
|
||||
alphaTokes["To"]=TO;
|
||||
alphaTokes["Step"]=STEP;
|
||||
alphaTokes["Next"]=NEXT;
|
||||
alphaTokes["Function"]=FUNCTION;
|
||||
alphaTokes["End Function"]=ENDFUNCTION;
|
||||
alphaTokes["Type"]=TYPE;
|
||||
alphaTokes["End Type"]=ENDTYPE;
|
||||
alphaTokes["Each"]=EACH;
|
||||
alphaTokes["Local"]=LOCAL;
|
||||
alphaTokes["Global"]=GLOBAL;
|
||||
alphaTokes["Field"]=FIELD;
|
||||
alphaTokes["Const"]=BBCONST;
|
||||
alphaTokes["Select"]=SELECT;
|
||||
alphaTokes["Case"]=CASE;
|
||||
alphaTokes["Default"]=DEFAULT;
|
||||
alphaTokes["End Select"]=ENDSELECT;
|
||||
alphaTokes["Repeat"]=REPEAT;
|
||||
alphaTokes["Until"]=UNTIL;
|
||||
alphaTokes["Forever"]=FOREVER;
|
||||
alphaTokes["Data"]=DATA;
|
||||
alphaTokes["Read"]=READ;
|
||||
alphaTokes["Restore"]=RESTORE;
|
||||
alphaTokes["Abs"]=ABS;
|
||||
alphaTokes["Sgn"]=SGN;
|
||||
alphaTokes["Mod"]=MOD;
|
||||
alphaTokes["Pi"]=PI;
|
||||
alphaTokes["True"]=BBTRUE;
|
||||
alphaTokes["False"]=BBFALSE;
|
||||
alphaTokes["Int"]=BBINT;
|
||||
alphaTokes["Float"]=BBFLOAT;
|
||||
alphaTokes["Str"]=BBSTR;
|
||||
alphaTokes["Include"]=INCLUDE;
|
||||
alphaTokes["Dim"] = DIM;
|
||||
alphaTokes["Goto"] = GOTO;
|
||||
alphaTokes["Gosub"] = GOSUB;
|
||||
alphaTokes["Return"] = RETURN;
|
||||
alphaTokes["Exit"] = EXIT;
|
||||
alphaTokes["If"] = IF;
|
||||
alphaTokes["Then"] = THEN;
|
||||
alphaTokes["Else"] = ELSE;
|
||||
alphaTokes["EndIf"] = ENDIF;
|
||||
alphaTokes["End If"] = ENDIF;
|
||||
alphaTokes["ElseIf"] = ELSEIF;
|
||||
alphaTokes["Else If"] = ELSEIF;
|
||||
alphaTokes["While"] = WHILE;
|
||||
alphaTokes["Wend"] = WEND;
|
||||
alphaTokes["For"] = FOR;
|
||||
alphaTokes["To"] = TO;
|
||||
alphaTokes["Step"] = STEP;
|
||||
alphaTokes["Next"] = NEXT;
|
||||
alphaTokes["Function"] = FUNCTION;
|
||||
alphaTokes["End Function"] = ENDFUNCTION;
|
||||
alphaTokes["Type"] = TYPE;
|
||||
alphaTokes["End Type"] = ENDTYPE;
|
||||
alphaTokes["Each"] = EACH;
|
||||
alphaTokes["Local"] = LOCAL;
|
||||
alphaTokes["Global"] = GLOBAL;
|
||||
alphaTokes["Field"] = FIELD;
|
||||
alphaTokes["Const"] = BBCONST;
|
||||
alphaTokes["Select"] = SELECT;
|
||||
alphaTokes["Case"] = CASE;
|
||||
alphaTokes["Default"] = DEFAULT;
|
||||
alphaTokes["End Select"] = ENDSELECT;
|
||||
alphaTokes["Repeat"] = REPEAT;
|
||||
alphaTokes["Until"] = UNTIL;
|
||||
alphaTokes["Forever"] = FOREVER;
|
||||
alphaTokes["Data"] = DATA;
|
||||
alphaTokes["Read"] = READ;
|
||||
alphaTokes["Restore"] = RESTORE;
|
||||
alphaTokes["Abs"] = ABS;
|
||||
alphaTokes["Sgn"] = SGN;
|
||||
alphaTokes["Mod"] = MOD;
|
||||
alphaTokes["Pi"] = PI;
|
||||
alphaTokes["True"] = BBTRUE;
|
||||
alphaTokes["False"] = BBFALSE;
|
||||
alphaTokes["Int"] = BBINT;
|
||||
alphaTokes["Float"] = BBFLOAT;
|
||||
alphaTokes["Str"] = BBSTR;
|
||||
alphaTokes["Include"] = INCLUDE;
|
||||
|
||||
alphaTokes["New"]=BBNEW;
|
||||
alphaTokes["Delete"]=BBDELETE;
|
||||
alphaTokes["First"]=FIRST;
|
||||
alphaTokes["Last"]=LAST;
|
||||
alphaTokes["Insert"]=INSERT;
|
||||
alphaTokes["Before"]=BEFORE;
|
||||
alphaTokes["After"]=AFTER;
|
||||
alphaTokes["Null"]=BBNULL;
|
||||
alphaTokes["Object"]=OBJECT;
|
||||
alphaTokes["Handle"]=BBHANDLE;
|
||||
alphaTokes["New"] = BBNEW;
|
||||
alphaTokes["Delete"] = BBDELETE;
|
||||
alphaTokes["First"] = FIRST;
|
||||
alphaTokes["Last"] = LAST;
|
||||
alphaTokes["Insert"] = INSERT;
|
||||
alphaTokes["Before"] = BEFORE;
|
||||
alphaTokes["After"] = AFTER;
|
||||
alphaTokes["Null"] = BBNULL;
|
||||
alphaTokes["Object"] = OBJECT;
|
||||
alphaTokes["Handle"] = BBHANDLE;
|
||||
|
||||
alphaTokes["And"]=AND;
|
||||
alphaTokes["Or"]=OR;
|
||||
alphaTokes["Xor"]=XOR;
|
||||
alphaTokes["Not"]=NOT;
|
||||
alphaTokes["Shl"]=SHL;
|
||||
alphaTokes["Shr"]=SHR;
|
||||
alphaTokes["Sar"]=SAR;
|
||||
alphaTokes["And"] = AND;
|
||||
alphaTokes["Or"] = OR;
|
||||
alphaTokes["Xor"] = XOR;
|
||||
alphaTokes["Not"] = NOT;
|
||||
alphaTokes["Shl"] = SHL;
|
||||
alphaTokes["Shr"] = SHR;
|
||||
alphaTokes["Sar"] = SAR;
|
||||
|
||||
map<string,int>::const_iterator it;
|
||||
for( it=alphaTokes.begin();it!=alphaTokes.end();++it ){
|
||||
lowerTokes[tolower(it->first)]=it->second;
|
||||
map<string, int>::const_iterator it;
|
||||
for (it = alphaTokes.begin(); it != alphaTokes.end(); ++it) {
|
||||
lowerTokes[tolower(it->first)] = it->second;
|
||||
}
|
||||
made=true;
|
||||
made = true;
|
||||
}
|
||||
|
||||
Toker::Toker( istream &in ):in(in),curr_row(-1){
|
||||
Toker::Toker(istream& in) : in(in), curr_row(-1)
|
||||
{
|
||||
makeKeywords();
|
||||
nextline();
|
||||
}
|
||||
|
||||
map<string,int> &Toker::getKeywords(){
|
||||
map<string, int>& Toker::getKeywords()
|
||||
{
|
||||
makeKeywords();
|
||||
return alphaTokes;
|
||||
}
|
||||
|
||||
int Toker::pos(){
|
||||
return ((curr_row)<<16)|(tokes[curr_toke].from);
|
||||
int Toker::pos()
|
||||
{
|
||||
return ((curr_row) << 16) | (tokes[curr_toke].from);
|
||||
}
|
||||
|
||||
int Toker::curr(){
|
||||
int Toker::curr()
|
||||
{
|
||||
return tokes[curr_toke].n;
|
||||
}
|
||||
|
||||
string Toker::text(){
|
||||
int from=tokes[curr_toke].from,to=tokes[curr_toke].to;
|
||||
return line.substr( from,to-from );
|
||||
string Toker::text()
|
||||
{
|
||||
int from = tokes[curr_toke].from, to = tokes[curr_toke].to;
|
||||
return line.substr(from, to - from);
|
||||
}
|
||||
|
||||
int Toker::lookAhead( int n ){
|
||||
return tokes[curr_toke+n].n;
|
||||
int Toker::lookAhead(int n)
|
||||
{
|
||||
return tokes[curr_toke + n].n;
|
||||
}
|
||||
|
||||
void Toker::nextline(){
|
||||
void Toker::nextline()
|
||||
{
|
||||
++curr_row;
|
||||
curr_toke=0;
|
||||
curr_toke = 0;
|
||||
tokes.clear();
|
||||
if( in.eof() ){
|
||||
line.resize(1);line[0]=EOF;
|
||||
tokes.push_back( Toke( EOF,0,1 ) );
|
||||
if (in.eof()) {
|
||||
line.resize(1);
|
||||
line[0] = EOF;
|
||||
tokes.push_back(Toke(EOF, 0, 1));
|
||||
return;
|
||||
}
|
||||
|
||||
getline( in,line );line+='\n';
|
||||
chars_toked+=line.size();
|
||||
getline(in, line);
|
||||
line += '\n';
|
||||
chars_toked += line.size();
|
||||
|
||||
for( int k=0;k<line.size(); ){
|
||||
int c=line[k],from=k;
|
||||
if( c=='\n' ){
|
||||
tokes.push_back( Toke( c,from,++k ) );
|
||||
for (int k = 0; k < line.size();) {
|
||||
int c = line[k], from = k;
|
||||
if (c == '\n') {
|
||||
tokes.push_back(Toke(c, from, ++k));
|
||||
continue;
|
||||
}
|
||||
if( isspace( c ) ){ ++k;continue; }
|
||||
if( c==';' ){
|
||||
for( ++k;line[k]!='\n';++k ){}
|
||||
if (isspace(c)) {
|
||||
++k;
|
||||
continue;
|
||||
}
|
||||
if( c=='.' && isdigit( line[k+1] ) ){
|
||||
for( k+=2;isdigit( line[k] );++k ){}
|
||||
tokes.push_back( Toke( FLOATCONST,from,k ) );
|
||||
if (c == ';') {
|
||||
for (++k; line[k] != '\n'; ++k) {
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if( isdigit( c ) ){
|
||||
for( ++k;isdigit( line[k] );++k ){}
|
||||
if( line[k]=='.' ){
|
||||
for( ++k;isdigit( line[k] );++k ){}
|
||||
tokes.push_back( Toke( FLOATCONST,from,k ) );
|
||||
if (c == '.' && isdigit(line[k + 1])) {
|
||||
for (k += 2; isdigit(line[k]); ++k) {
|
||||
}
|
||||
tokes.push_back(Toke(FLOATCONST, from, k));
|
||||
continue;
|
||||
}
|
||||
if (isdigit(c)) {
|
||||
for (++k; isdigit(line[k]); ++k) {
|
||||
}
|
||||
if (line[k] == '.') {
|
||||
for (++k; isdigit(line[k]); ++k) {
|
||||
}
|
||||
tokes.push_back(Toke(FLOATCONST, from, k));
|
||||
continue;
|
||||
}
|
||||
tokes.push_back( Toke( INTCONST,from,k ) );
|
||||
tokes.push_back(Toke(INTCONST, from, k));
|
||||
continue;
|
||||
}
|
||||
if( c=='%' && (line[k+1]=='0' || line[k+1]=='1') ){
|
||||
for( k+=2;line[k]=='0'||line[k]=='1';++k ){}
|
||||
tokes.push_back( Toke( BINCONST,from,k ) );
|
||||
if (c == '%' && (line[k + 1] == '0' || line[k + 1] == '1')) {
|
||||
for (k += 2; line[k] == '0' || line[k] == '1'; ++k) {
|
||||
}
|
||||
tokes.push_back(Toke(BINCONST, from, k));
|
||||
continue;
|
||||
}
|
||||
if( c=='$' && isxdigit( line[k+1] ) ){
|
||||
for( k+=2;isxdigit( line[k] );++k ){}
|
||||
tokes.push_back( Toke( HEXCONST,from,k ) );
|
||||
if (c == '$' && isxdigit(line[k + 1])) {
|
||||
for (k += 2; isxdigit(line[k]); ++k) {
|
||||
}
|
||||
tokes.push_back(Toke(HEXCONST, from, k));
|
||||
continue;
|
||||
}
|
||||
if( isalpha( c ) ){
|
||||
for( ++k;isalnum( line[k] ) || line[k]=='_';++k ){}
|
||||
if (isalpha(c)) {
|
||||
for (++k; isalnum(line[k]) || line[k] == '_'; ++k) {
|
||||
}
|
||||
|
||||
string ident=tolower(line.substr(from,k-from));
|
||||
string ident = tolower(line.substr(from, k - from));
|
||||
|
||||
if( line[k]==' ' && isalpha( line[k+1] ) ){
|
||||
int t=k;
|
||||
for( t+=2;isalnum( line[t] ) || line[t]=='_';++t ){}
|
||||
string s=tolower(line.substr(from,t-from));
|
||||
if( lowerTokes.find(s)!=lowerTokes.end() ){
|
||||
k=t;ident=s;
|
||||
if (line[k] == ' ' && isalpha(line[k + 1])) {
|
||||
int t = k;
|
||||
for (t += 2; isalnum(line[t]) || line[t] == '_'; ++t) {
|
||||
}
|
||||
string s = tolower(line.substr(from, t - from));
|
||||
if (lowerTokes.find(s) != lowerTokes.end()) {
|
||||
k = t;
|
||||
ident = s;
|
||||
}
|
||||
}
|
||||
|
||||
map<string,int>::iterator it=lowerTokes.find( ident );
|
||||
map<string, int>::iterator it = lowerTokes.find(ident);
|
||||
|
||||
if( it==lowerTokes.end() ){
|
||||
for( int n=from;n<k;++n ) line[n]=tolower(line[n]);
|
||||
tokes.push_back( Toke( IDENT,from,k ) );
|
||||
if (it == lowerTokes.end()) {
|
||||
for (int n = from; n < k; ++n)
|
||||
line[n] = tolower(line[n]);
|
||||
tokes.push_back(Toke(IDENT, from, k));
|
||||
continue;
|
||||
}
|
||||
|
||||
tokes.push_back( Toke( it->second,from,k ) );
|
||||
tokes.push_back(Toke(it->second, from, k));
|
||||
continue;
|
||||
}
|
||||
if( c=='\"' ){
|
||||
for( ++k;line[k]!='\"' && line[k]!='\n';++k ){}
|
||||
if( line[k]=='\"' ) ++k;
|
||||
tokes.push_back( Toke( STRINGCONST,from,k ) );
|
||||
if (c == '\"') {
|
||||
for (++k; line[k] != '\"' && line[k] != '\n'; ++k) {
|
||||
}
|
||||
if (line[k] == '\"')
|
||||
++k;
|
||||
tokes.push_back(Toke(STRINGCONST, from, k));
|
||||
continue;
|
||||
}
|
||||
int n=line[k+1];
|
||||
if( (c=='<'&&n=='>')||(c=='>'&&n=='<') ){
|
||||
tokes.push_back( Toke( NE,from,k+=2 ) );
|
||||
int n = line[k + 1];
|
||||
if ((c == '<' && n == '>') || (c == '>' && n == '<')) {
|
||||
tokes.push_back(Toke(NE, from, k += 2));
|
||||
continue;
|
||||
}
|
||||
if( (c=='<'&&n=='=')||(c=='='&&n=='<') ){
|
||||
tokes.push_back( Toke( LE,from,k+=2 ) );
|
||||
if ((c == '<' && n == '=') || (c == '=' && n == '<')) {
|
||||
tokes.push_back(Toke(LE, from, k += 2));
|
||||
continue;
|
||||
}
|
||||
if( (c=='>'&&n=='=')||(c=='='&&n=='>') ){
|
||||
tokes.push_back( Toke( GE,from,k+=2 ) );
|
||||
if ((c == '>' && n == '=') || (c == '=' && n == '>')) {
|
||||
tokes.push_back(Toke(GE, from, k += 2));
|
||||
continue;
|
||||
}
|
||||
tokes.push_back( Toke( c,from,++k ) );
|
||||
tokes.push_back(Toke(c, from, ++k));
|
||||
}
|
||||
if( !tokes.size() ) exit(0);
|
||||
if (!tokes.size())
|
||||
exit(0);
|
||||
}
|
||||
|
||||
int Toker::next(){
|
||||
if( ++curr_toke==tokes.size() ) nextline();
|
||||
int Toker::next()
|
||||
{
|
||||
if (++curr_toke == tokes.size())
|
||||
nextline();
|
||||
return curr();
|
||||
}
|
||||
|
||||
+87
-35
@@ -8,54 +8,106 @@
|
||||
#ifndef TOKER_H
|
||||
#define TOKER_H
|
||||
|
||||
enum{
|
||||
DIM=0x8000,GOTO,GOSUB,EXIT,RETURN,
|
||||
IF,THEN,ELSE,ENDIF,ELSEIF,
|
||||
WHILE,WEND,
|
||||
FOR,TO,STEP,NEXT,
|
||||
FUNCTION,ENDFUNCTION,
|
||||
TYPE,ENDTYPE,EACH,
|
||||
GLOBAL,LOCAL,FIELD,BBCONST,
|
||||
SELECT,CASE,DEFAULT,ENDSELECT,
|
||||
REPEAT,UNTIL,FOREVER,
|
||||
DATA,READ,RESTORE,
|
||||
ABS,SGN,MOD,
|
||||
PI,BBTRUE,BBFALSE,
|
||||
BBINT,BBFLOAT,BBSTR,
|
||||
enum {
|
||||
DIM = 0x8000,
|
||||
GOTO,
|
||||
GOSUB,
|
||||
EXIT,
|
||||
RETURN,
|
||||
IF,
|
||||
THEN,
|
||||
ELSE,
|
||||
ENDIF,
|
||||
ELSEIF,
|
||||
WHILE,
|
||||
WEND,
|
||||
FOR,
|
||||
TO,
|
||||
STEP,
|
||||
NEXT,
|
||||
FUNCTION,
|
||||
ENDFUNCTION,
|
||||
TYPE,
|
||||
ENDTYPE,
|
||||
EACH,
|
||||
GLOBAL,
|
||||
LOCAL,
|
||||
FIELD,
|
||||
BBCONST,
|
||||
SELECT,
|
||||
CASE,
|
||||
DEFAULT,
|
||||
ENDSELECT,
|
||||
REPEAT,
|
||||
UNTIL,
|
||||
FOREVER,
|
||||
DATA,
|
||||
READ,
|
||||
RESTORE,
|
||||
ABS,
|
||||
SGN,
|
||||
MOD,
|
||||
PI,
|
||||
BBTRUE,
|
||||
BBFALSE,
|
||||
BBINT,
|
||||
BBFLOAT,
|
||||
BBSTR,
|
||||
INCLUDE,
|
||||
|
||||
BBNEW,BBDELETE,FIRST,LAST,INSERT,BEFORE,AFTER,BBNULL,
|
||||
OBJECT,BBHANDLE,
|
||||
AND,OR,XOR,NOT,SHL,SHR,SAR,
|
||||
BBNEW,
|
||||
BBDELETE,
|
||||
FIRST,
|
||||
LAST,
|
||||
INSERT,
|
||||
BEFORE,
|
||||
AFTER,
|
||||
BBNULL,
|
||||
OBJECT,
|
||||
BBHANDLE,
|
||||
AND,
|
||||
OR,
|
||||
XOR,
|
||||
NOT,
|
||||
SHL,
|
||||
SHR,
|
||||
SAR,
|
||||
|
||||
LE,GE,NE,
|
||||
IDENT,INTCONST,BINCONST,HEXCONST,FLOATCONST,STRINGCONST
|
||||
LE,
|
||||
GE,
|
||||
NE,
|
||||
IDENT,
|
||||
INTCONST,
|
||||
BINCONST,
|
||||
HEXCONST,
|
||||
FLOATCONST,
|
||||
STRINGCONST
|
||||
};
|
||||
|
||||
class Toker{
|
||||
public:
|
||||
Toker( istream &in );
|
||||
class Toker {
|
||||
public:
|
||||
Toker(istream& in);
|
||||
|
||||
int pos();
|
||||
int curr();
|
||||
int next();
|
||||
int pos();
|
||||
int curr();
|
||||
int next();
|
||||
string text();
|
||||
int lookAhead( int n );
|
||||
int lookAhead(int n);
|
||||
|
||||
static int chars_toked;
|
||||
|
||||
static map<string,int> &getKeywords();
|
||||
static map<string, int>& getKeywords();
|
||||
|
||||
private:
|
||||
struct Toke{
|
||||
int n,from,to;
|
||||
Toke( int n,int f,int t ):n(n),from(f),to(t){}
|
||||
private:
|
||||
struct Toke {
|
||||
int n, from, to;
|
||||
Toke(int n, int f, int t) : n(n), from(f), to(t) {}
|
||||
};
|
||||
istream ∈
|
||||
string line;
|
||||
istream& in;
|
||||
string line;
|
||||
vector<Toke> tokes;
|
||||
void nextline();
|
||||
int curr_row,curr_toke;
|
||||
void nextline();
|
||||
int curr_row, curr_toke;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
+52
-39
@@ -1,61 +1,74 @@
|
||||
|
||||
#include "std.hpp"
|
||||
#include "type.hpp"
|
||||
#include "std.hpp"
|
||||
|
||||
static struct v_type : public Type{
|
||||
bool canCastTo( Type *t ){
|
||||
return t==Type::void_type;
|
||||
static struct v_type : public Type {
|
||||
bool canCastTo(Type* t)
|
||||
{
|
||||
return t == Type::void_type;
|
||||
}
|
||||
}v;
|
||||
} v;
|
||||
|
||||
static struct i_type : public Type{
|
||||
bool intType(){
|
||||
return true;
|
||||
}
|
||||
bool canCastTo( Type *t ){
|
||||
return t==Type::int_type || t==Type::float_type || t==Type::string_type;
|
||||
}
|
||||
}i;
|
||||
|
||||
static struct f_type : public Type{
|
||||
bool floatType(){
|
||||
static struct i_type : public Type {
|
||||
bool intType()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
bool canCastTo( Type *t ){
|
||||
return t==Type::int_type || t==Type::float_type || t==Type::string_type;
|
||||
bool canCastTo(Type* t)
|
||||
{
|
||||
return t == Type::int_type || t == Type::float_type || t == Type::string_type;
|
||||
}
|
||||
}f;
|
||||
} i;
|
||||
|
||||
static struct s_type : public Type{
|
||||
bool stringType(){
|
||||
static struct f_type : public Type {
|
||||
bool floatType()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
bool canCastTo( Type *t ){
|
||||
return t==Type::int_type || t==Type::float_type || t==Type::string_type;
|
||||
bool canCastTo(Type* t)
|
||||
{
|
||||
return t == Type::int_type || t == Type::float_type || t == Type::string_type;
|
||||
}
|
||||
}s;
|
||||
} f;
|
||||
|
||||
bool StructType::canCastTo( Type *t ){
|
||||
return t==this || t==Type::null_type || (this==Type::null_type && t->structType());
|
||||
static struct s_type : public Type {
|
||||
bool stringType()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
bool canCastTo(Type* t)
|
||||
{
|
||||
return t == Type::int_type || t == Type::float_type || t == Type::string_type;
|
||||
}
|
||||
} s;
|
||||
|
||||
bool StructType::canCastTo(Type* t)
|
||||
{
|
||||
return t == this || t == Type::null_type || (this == Type::null_type && t->structType());
|
||||
}
|
||||
|
||||
bool VectorType::canCastTo( Type *t ){
|
||||
if( this==t ) return true;
|
||||
if( VectorType *v=t->vectorType() ){
|
||||
if( elementType!=v->elementType ) return false;
|
||||
if( sizes.size()!=v->sizes.size() ) return false;
|
||||
for( int k=0;k<sizes.size();++k ){
|
||||
if( sizes[k]!=v->sizes[k] ) return false;
|
||||
bool VectorType::canCastTo(Type* t)
|
||||
{
|
||||
if (this == t)
|
||||
return true;
|
||||
if (VectorType* v = t->vectorType()) {
|
||||
if (elementType != v->elementType)
|
||||
return false;
|
||||
if (sizes.size() != v->sizes.size())
|
||||
return false;
|
||||
for (int k = 0; k < sizes.size(); ++k) {
|
||||
if (sizes[k] != v->sizes[k])
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static StructType n( "Null" );
|
||||
static StructType n("Null");
|
||||
|
||||
Type *Type::void_type=&v;
|
||||
Type *Type::int_type=&i;
|
||||
Type *Type::float_type=&f;
|
||||
Type *Type::string_type=&s;
|
||||
Type *Type::null_type=&n;
|
||||
Type* Type::void_type = &v;
|
||||
Type* Type::int_type = &i;
|
||||
Type* Type::float_type = &f;
|
||||
Type* Type::string_type = &s;
|
||||
Type* Type::null_type = &n;
|
||||
|
||||
+94
-45
@@ -10,70 +10,119 @@ struct StructType;
|
||||
struct ConstType;
|
||||
struct VectorType;
|
||||
|
||||
struct Type{
|
||||
virtual ~Type(){}
|
||||
struct Type {
|
||||
virtual ~Type() {}
|
||||
|
||||
virtual bool intType(){ return 0;}
|
||||
virtual bool floatType(){ return 0; }
|
||||
virtual bool stringType(){ return 0; }
|
||||
virtual bool intType()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
virtual bool floatType()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
virtual bool stringType()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
//casts to inherited types
|
||||
virtual FuncType *funcType(){ return 0; }
|
||||
virtual ArrayType *arrayType(){ return 0; }
|
||||
virtual StructType *structType(){ return 0; }
|
||||
virtual ConstType *constType(){ return 0; }
|
||||
virtual VectorType *vectorType(){ return 0; }
|
||||
virtual FuncType* funcType()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
virtual ArrayType* arrayType()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
virtual StructType* structType()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
virtual ConstType* constType()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
virtual VectorType* vectorType()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
//operators
|
||||
virtual bool canCastTo( Type *t ){ return this==t; }
|
||||
virtual bool canCastTo(Type* t)
|
||||
{
|
||||
return this == t;
|
||||
}
|
||||
|
||||
//built in types
|
||||
static Type *void_type,*int_type,*float_type,*string_type,*null_type;
|
||||
static Type *void_type, *int_type, *float_type, *string_type, *null_type;
|
||||
};
|
||||
|
||||
struct FuncType : public Type{
|
||||
Type *returnType;
|
||||
DeclSeq *params;
|
||||
bool userlib,cfunc;
|
||||
FuncType( Type *t,DeclSeq *p,bool ulib,bool cfn ):returnType(t),params(p),userlib(ulib),cfunc(cfn){}
|
||||
~FuncType(){ delete params; }
|
||||
FuncType *funcType(){ return this; }
|
||||
struct FuncType : public Type {
|
||||
Type* returnType;
|
||||
DeclSeq* params;
|
||||
bool userlib, cfunc;
|
||||
FuncType(Type* t, DeclSeq* p, bool ulib, bool cfn) : returnType(t), params(p), userlib(ulib), cfunc(cfn) {}
|
||||
~FuncType()
|
||||
{
|
||||
delete params;
|
||||
}
|
||||
FuncType* funcType()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
};
|
||||
|
||||
struct ArrayType : public Type{
|
||||
Type *elementType;int dims;
|
||||
ArrayType( Type *t,int n ):elementType(t),dims(n){}
|
||||
ArrayType *arrayType(){ return this; }
|
||||
struct ArrayType : public Type {
|
||||
Type* elementType;
|
||||
int dims;
|
||||
ArrayType(Type* t, int n) : elementType(t), dims(n) {}
|
||||
ArrayType* arrayType()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
};
|
||||
|
||||
struct StructType : public Type{
|
||||
string ident;
|
||||
DeclSeq *fields;
|
||||
StructType( const string &i ):ident(i),fields(0){}
|
||||
StructType( const string &i,DeclSeq *f ):ident(i),fields( f ){}
|
||||
~StructType(){ delete fields; }
|
||||
StructType *structType(){ return this; }
|
||||
virtual bool canCastTo( Type *t );
|
||||
struct StructType : public Type {
|
||||
string ident;
|
||||
DeclSeq* fields;
|
||||
StructType(const string& i) : ident(i), fields(0) {}
|
||||
StructType(const string& i, DeclSeq* f) : ident(i), fields(f) {}
|
||||
~StructType()
|
||||
{
|
||||
delete fields;
|
||||
}
|
||||
StructType* structType()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
virtual bool canCastTo(Type* t);
|
||||
};
|
||||
|
||||
struct ConstType : public Type{
|
||||
Type *valueType;
|
||||
int intValue;
|
||||
float floatValue;
|
||||
struct ConstType : public Type {
|
||||
Type* valueType;
|
||||
int intValue;
|
||||
float floatValue;
|
||||
string stringValue;
|
||||
ConstType( int n ):intValue(n),valueType(Type::int_type){}
|
||||
ConstType( float n ):floatValue(n),valueType(Type::float_type){}
|
||||
ConstType( const string &n ):stringValue(n),valueType(Type::string_type){}
|
||||
ConstType *constType(){ return this; }
|
||||
ConstType(int n) : intValue(n), valueType(Type::int_type) {}
|
||||
ConstType(float n) : floatValue(n), valueType(Type::float_type) {}
|
||||
ConstType(const string& n) : stringValue(n), valueType(Type::string_type) {}
|
||||
ConstType* constType()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
};
|
||||
|
||||
struct VectorType : public Type{
|
||||
string label;
|
||||
Type *elementType;
|
||||
struct VectorType : public Type {
|
||||
string label;
|
||||
Type* elementType;
|
||||
vector<int> sizes;
|
||||
VectorType( const string &l,Type *t,const vector<int> &szs ):label(l),elementType(t),sizes(szs){}
|
||||
VectorType *vectorType(){ return this; }
|
||||
virtual bool canCastTo( Type *t );
|
||||
VectorType(const string& l, Type* t, const vector<int>& szs) : label(l), elementType(t), sizes(szs) {}
|
||||
VectorType* vectorType()
|
||||
{
|
||||
return this;
|
||||
}
|
||||
virtual bool canCastTo(Type* t);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
+4
-5
@@ -4,12 +4,11 @@
|
||||
|
||||
struct Type;
|
||||
|
||||
struct Var{
|
||||
struct Var {
|
||||
int index;
|
||||
Type* type;
|
||||
|
||||
int index;
|
||||
Type *type;
|
||||
|
||||
Var( int i,Type *t ):index(i),type(t){}
|
||||
Var(int i, Type* t) : index(i), type(t) {}
|
||||
};
|
||||
|
||||
#endif
|
||||
+130
-98
@@ -1,158 +1,190 @@
|
||||
|
||||
#include "std.hpp"
|
||||
#include "nodes.hpp"
|
||||
#include "std.hpp"
|
||||
|
||||
//////////////////////////////////
|
||||
// Common get/set for variables //
|
||||
//////////////////////////////////
|
||||
TNode *VarNode::load( Codegen *g ){
|
||||
TNode *t=translate( g );
|
||||
if( sem_type==Type::string_type ) return call( "__bbStrLoad",t );
|
||||
return mem( t );
|
||||
TNode* VarNode::load(Codegen* g)
|
||||
{
|
||||
TNode* t = translate(g);
|
||||
if (sem_type == Type::string_type)
|
||||
return call("__bbStrLoad", t);
|
||||
return mem(t);
|
||||
}
|
||||
|
||||
TNode *VarNode::store( Codegen *g,TNode *n ){
|
||||
TNode *t=translate( g );
|
||||
if( sem_type->structType() ) return call( "__bbObjStore",t,n );
|
||||
if( sem_type==Type::string_type ) return call( "__bbStrStore",t,n );
|
||||
return move( n,mem( t ) );
|
||||
TNode* VarNode::store(Codegen* g, TNode* n)
|
||||
{
|
||||
TNode* t = translate(g);
|
||||
if (sem_type->structType())
|
||||
return call("__bbObjStore", t, n);
|
||||
if (sem_type == Type::string_type)
|
||||
return call("__bbStrStore", t, n);
|
||||
return move(n, mem(t));
|
||||
}
|
||||
|
||||
bool VarNode::isObjParam(){
|
||||
bool VarNode::isObjParam()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//////////////////
|
||||
// Declared var //
|
||||
//////////////////
|
||||
void DeclVarNode::semant( Environ *e ){
|
||||
void DeclVarNode::semant(Environ* e) {}
|
||||
|
||||
TNode* DeclVarNode::translate(Codegen* g)
|
||||
{
|
||||
if (sem_decl->kind == DECL_GLOBAL)
|
||||
return global("_v" + sem_decl->name);
|
||||
return local(sem_decl->offset);
|
||||
}
|
||||
|
||||
TNode *DeclVarNode::translate( Codegen *g ){
|
||||
if( sem_decl->kind==DECL_GLOBAL ) return global( "_v"+sem_decl->name );
|
||||
return local( sem_decl->offset );
|
||||
}
|
||||
|
||||
TNode *DeclVarNode::store( Codegen *g,TNode *n ){
|
||||
if( isObjParam() ){
|
||||
TNode *t=translate( g );
|
||||
return move( n,mem( t ) );
|
||||
TNode* DeclVarNode::store(Codegen* g, TNode* n)
|
||||
{
|
||||
if (isObjParam()) {
|
||||
TNode* t = translate(g);
|
||||
return move(n, mem(t));
|
||||
}
|
||||
return VarNode::store( g,n );
|
||||
return VarNode::store(g, n);
|
||||
}
|
||||
|
||||
bool DeclVarNode::isObjParam(){
|
||||
return sem_type->structType() && sem_decl->kind==DECL_PARAM;
|
||||
bool DeclVarNode::isObjParam()
|
||||
{
|
||||
return sem_type->structType() && sem_decl->kind == DECL_PARAM;
|
||||
}
|
||||
|
||||
///////////////
|
||||
// Ident var //
|
||||
///////////////
|
||||
void IdentVarNode::semant( Environ *e ){
|
||||
if( sem_decl ) return;
|
||||
Type *t=tagType( tag,e );if( !t ) t=Type::int_type;
|
||||
if( sem_decl=e->findDecl( ident ) ){
|
||||
if( !(sem_decl->kind&(DECL_GLOBAL|DECL_LOCAL|DECL_PARAM)) ){
|
||||
ex( "Identifier '"+sem_decl->name+"' may not be used like this" );
|
||||
void IdentVarNode::semant(Environ* e)
|
||||
{
|
||||
if (sem_decl)
|
||||
return;
|
||||
Type* t = tagType(tag, e);
|
||||
if (!t)
|
||||
t = Type::int_type;
|
||||
if (sem_decl = e->findDecl(ident)) {
|
||||
if (!(sem_decl->kind & (DECL_GLOBAL | DECL_LOCAL | DECL_PARAM))) {
|
||||
ex("Identifier '" + sem_decl->name + "' may not be used like this");
|
||||
}
|
||||
Type *ty=sem_decl->type;
|
||||
if( ty->constType() ) ty=ty->constType()->valueType;
|
||||
if( tag.size() && t!=ty ) ex( "Variable type mismatch" );
|
||||
}else{
|
||||
Type* ty = sem_decl->type;
|
||||
if (ty->constType())
|
||||
ty = ty->constType()->valueType;
|
||||
if (tag.size() && t != ty)
|
||||
ex("Variable type mismatch");
|
||||
} else {
|
||||
//ugly auto decl!
|
||||
sem_decl=e->decls->insertDecl( ident,t,DECL_LOCAL );
|
||||
sem_decl = e->decls->insertDecl(ident, t, DECL_LOCAL);
|
||||
}
|
||||
sem_type=sem_decl->type;
|
||||
sem_type = sem_decl->type;
|
||||
}
|
||||
|
||||
/////////////////
|
||||
// Indexed Var //
|
||||
/////////////////
|
||||
void ArrayVarNode::semant( Environ *e ){
|
||||
exprs->semant( e );
|
||||
exprs->castTo( Type::int_type,e );
|
||||
Type *t=e->findType( tag );
|
||||
sem_decl=e->findDecl( ident );
|
||||
if( !sem_decl || !(sem_decl->kind&DECL_ARRAY) ) ex( "Array not found" );
|
||||
ArrayType *a=sem_decl->type->arrayType();
|
||||
if( t && t!=a->elementType ) ex( "array type mismtach" );
|
||||
if( a->dims!=exprs->size() ) ex( "incorrect number of dimensions" );
|
||||
sem_type=a->elementType;
|
||||
void ArrayVarNode::semant(Environ* e)
|
||||
{
|
||||
exprs->semant(e);
|
||||
exprs->castTo(Type::int_type, e);
|
||||
Type* t = e->findType(tag);
|
||||
sem_decl = e->findDecl(ident);
|
||||
if (!sem_decl || !(sem_decl->kind & DECL_ARRAY))
|
||||
ex("Array not found");
|
||||
ArrayType* a = sem_decl->type->arrayType();
|
||||
if (t && t != a->elementType)
|
||||
ex("array type mismtach");
|
||||
if (a->dims != exprs->size())
|
||||
ex("incorrect number of dimensions");
|
||||
sem_type = a->elementType;
|
||||
}
|
||||
|
||||
TNode *ArrayVarNode::translate( Codegen *g ){
|
||||
TNode *t=0;
|
||||
for( int k=0;k<exprs->size();++k ){
|
||||
TNode *e=exprs->exprs[k]->translate( g );
|
||||
if( k ){
|
||||
TNode *s=mem( add( global( "_a"+ident ),iconst( k*4+8 ) ) );
|
||||
e=add( t,mul( e,s ) );
|
||||
TNode* ArrayVarNode::translate(Codegen* g)
|
||||
{
|
||||
TNode* t = 0;
|
||||
for (int k = 0; k < exprs->size(); ++k) {
|
||||
TNode* e = exprs->exprs[k]->translate(g);
|
||||
if (k) {
|
||||
TNode* s = mem(add(global("_a" + ident), iconst(k * 4 + 8)));
|
||||
e = add(t, mul(e, s));
|
||||
}
|
||||
if( g->debug ){
|
||||
TNode *s=mem( add( global( "_a"+ident ),iconst( k*4+12 ) ) );
|
||||
t=jumpge( e,s,"__bbArrayBoundsEx" );
|
||||
}else t=e;
|
||||
if (g->debug) {
|
||||
TNode* s = mem(add(global("_a" + ident), iconst(k * 4 + 12)));
|
||||
t = jumpge(e, s, "__bbArrayBoundsEx");
|
||||
} else
|
||||
t = e;
|
||||
}
|
||||
t=add( mem( global( "_a"+ident ) ),mul( t,iconst( 4 ) ) );
|
||||
t = add(mem(global("_a" + ident)), mul(t, iconst(4)));
|
||||
return t;
|
||||
}
|
||||
|
||||
///////////////
|
||||
// Field var //
|
||||
///////////////
|
||||
void FieldVarNode::semant( Environ *e ){
|
||||
expr=expr->semant( e );
|
||||
StructType *s=expr->sem_type->structType();
|
||||
if( !s ) ex( "Variable must be a Type" );
|
||||
sem_field=s->fields->findDecl( ident );
|
||||
if( !sem_field ) ex( "Type field not found" );
|
||||
sem_type=sem_field->type;
|
||||
void FieldVarNode::semant(Environ* e)
|
||||
{
|
||||
expr = expr->semant(e);
|
||||
StructType* s = expr->sem_type->structType();
|
||||
if (!s)
|
||||
ex("Variable must be a Type");
|
||||
sem_field = s->fields->findDecl(ident);
|
||||
if (!sem_field)
|
||||
ex("Type field not found");
|
||||
sem_type = sem_field->type;
|
||||
}
|
||||
|
||||
TNode *FieldVarNode::translate( Codegen *g ){
|
||||
TNode *t=expr->translate( g );
|
||||
if( g->debug ) t=jumpf( t,"__bbNullObjEx" );
|
||||
t=mem( t );if( g->debug ) t=jumpf( t,"__bbNullObjEx" );
|
||||
return add( t,iconst( sem_field->offset ) );
|
||||
TNode* FieldVarNode::translate(Codegen* g)
|
||||
{
|
||||
TNode* t = expr->translate(g);
|
||||
if (g->debug)
|
||||
t = jumpf(t, "__bbNullObjEx");
|
||||
t = mem(t);
|
||||
if (g->debug)
|
||||
t = jumpf(t, "__bbNullObjEx");
|
||||
return add(t, iconst(sem_field->offset));
|
||||
}
|
||||
|
||||
////////////////
|
||||
// Vector var //
|
||||
////////////////
|
||||
void VectorVarNode::semant( Environ *e ){
|
||||
expr=expr->semant( e );
|
||||
vec_type=expr->sem_type->vectorType();
|
||||
if( !vec_type ) ex( "Variable must be a Blitz array" );
|
||||
if( vec_type->sizes.size()!=exprs->size() ) ex( "Incorrect number of subscripts" );
|
||||
exprs->semant( e );
|
||||
exprs->castTo( Type::int_type,e );
|
||||
for( int k=0;k<exprs->size();++k ){
|
||||
if( ConstNode *t=exprs->exprs[k]->constNode() ){
|
||||
if( t->intValue()>=vec_type->sizes[k] ){
|
||||
ex( "Blitz array subscript out of range" );
|
||||
void VectorVarNode::semant(Environ* e)
|
||||
{
|
||||
expr = expr->semant(e);
|
||||
vec_type = expr->sem_type->vectorType();
|
||||
if (!vec_type)
|
||||
ex("Variable must be a Blitz array");
|
||||
if (vec_type->sizes.size() != exprs->size())
|
||||
ex("Incorrect number of subscripts");
|
||||
exprs->semant(e);
|
||||
exprs->castTo(Type::int_type, e);
|
||||
for (int k = 0; k < exprs->size(); ++k) {
|
||||
if (ConstNode* t = exprs->exprs[k]->constNode()) {
|
||||
if (t->intValue() >= vec_type->sizes[k]) {
|
||||
ex("Blitz array subscript out of range");
|
||||
}
|
||||
}
|
||||
}
|
||||
sem_type=vec_type->elementType;
|
||||
sem_type = vec_type->elementType;
|
||||
}
|
||||
|
||||
TNode *VectorVarNode::translate( Codegen *g ){
|
||||
int sz=4;
|
||||
TNode *t=0;
|
||||
for( int k=0;k<exprs->size();++k ){
|
||||
TNode *p;
|
||||
ExprNode *e=exprs->exprs[k];
|
||||
if( ConstNode *t=e->constNode() ){
|
||||
p=iconst( t->intValue() * sz );
|
||||
}else{
|
||||
p=e->translate( g );
|
||||
if( g->debug ){
|
||||
p=jumpge( p,iconst( vec_type->sizes[k] ),"__bbVecBoundsEx" );
|
||||
TNode* VectorVarNode::translate(Codegen* g)
|
||||
{
|
||||
int sz = 4;
|
||||
TNode* t = 0;
|
||||
for (int k = 0; k < exprs->size(); ++k) {
|
||||
TNode* p;
|
||||
ExprNode* e = exprs->exprs[k];
|
||||
if (ConstNode* t = e->constNode()) {
|
||||
p = iconst(t->intValue() * sz);
|
||||
} else {
|
||||
p = e->translate(g);
|
||||
if (g->debug) {
|
||||
p = jumpge(p, iconst(vec_type->sizes[k]), "__bbVecBoundsEx");
|
||||
}
|
||||
p=mul( p,iconst( sz ) );
|
||||
p = mul(p, iconst(sz));
|
||||
}
|
||||
sz=sz*vec_type->sizes[k];
|
||||
t=t ? add( t,p ) : p;
|
||||
sz = sz * vec_type->sizes[k];
|
||||
t = t ? add(t, p) : p;
|
||||
}
|
||||
return add( t,expr->translate( g ) );
|
||||
return add(t, expr->translate(g));
|
||||
}
|
||||
|
||||
+56
-42
@@ -4,64 +4,78 @@
|
||||
|
||||
#include "varnode.hpp"
|
||||
|
||||
struct VarNode : public Node{
|
||||
Type *sem_type;
|
||||
struct VarNode : public Node {
|
||||
Type* sem_type;
|
||||
|
||||
//get set var
|
||||
TNode *load( Codegen *g );
|
||||
virtual TNode *store( Codegen *g,TNode *n );
|
||||
virtual bool isObjParam();
|
||||
TNode* load(Codegen* g);
|
||||
virtual TNode* store(Codegen* g, TNode* n);
|
||||
virtual bool isObjParam();
|
||||
|
||||
//addr of var
|
||||
virtual void semant( Environ *e )=0;
|
||||
virtual TNode *translate( Codegen *g )=0;
|
||||
virtual void semant(Environ* e) = 0;
|
||||
virtual TNode* translate(Codegen* g) = 0;
|
||||
};
|
||||
|
||||
#include "decl.hpp"
|
||||
|
||||
struct DeclVarNode : public VarNode{
|
||||
Decl *sem_decl;
|
||||
DeclVarNode( Decl *d=0 ):sem_decl(d){ if( d ) sem_type=d->type; }
|
||||
void semant( Environ *e );
|
||||
TNode *translate( Codegen *g );
|
||||
virtual TNode *store( Codegen *g,TNode *n );
|
||||
bool isObjParam();
|
||||
struct DeclVarNode : public VarNode {
|
||||
Decl* sem_decl;
|
||||
DeclVarNode(Decl* d = 0) : sem_decl(d)
|
||||
{
|
||||
if (d)
|
||||
sem_type = d->type;
|
||||
}
|
||||
void semant(Environ* e);
|
||||
TNode* translate(Codegen* g);
|
||||
virtual TNode* store(Codegen* g, TNode* n);
|
||||
bool isObjParam();
|
||||
};
|
||||
|
||||
struct IdentVarNode : public DeclVarNode{
|
||||
string ident,tag;
|
||||
IdentVarNode( const string &i,const string &t ):ident(i),tag(t){}
|
||||
void semant( Environ *e );
|
||||
struct IdentVarNode : public DeclVarNode {
|
||||
string ident, tag;
|
||||
IdentVarNode(const string& i, const string& t) : ident(i), tag(t) {}
|
||||
void semant(Environ* e);
|
||||
};
|
||||
|
||||
struct ArrayVarNode : public VarNode{
|
||||
string ident,tag;
|
||||
ExprSeqNode *exprs;
|
||||
Decl *sem_decl;
|
||||
ArrayVarNode( const string &i,const string &t,ExprSeqNode *e ):ident(i),tag(t),exprs(e){}
|
||||
~ArrayVarNode(){ delete exprs; }
|
||||
void semant( Environ *e );
|
||||
TNode *translate( Codegen *g );
|
||||
struct ArrayVarNode : public VarNode {
|
||||
string ident, tag;
|
||||
ExprSeqNode* exprs;
|
||||
Decl* sem_decl;
|
||||
ArrayVarNode(const string& i, const string& t, ExprSeqNode* e) : ident(i), tag(t), exprs(e) {}
|
||||
~ArrayVarNode()
|
||||
{
|
||||
delete exprs;
|
||||
}
|
||||
void semant(Environ* e);
|
||||
TNode* translate(Codegen* g);
|
||||
};
|
||||
|
||||
struct FieldVarNode : public VarNode{
|
||||
ExprNode *expr;
|
||||
string ident,tag;
|
||||
Decl *sem_field;
|
||||
FieldVarNode( ExprNode *e,const string &i,const string &t ):expr(e),ident(i),tag(t){}
|
||||
~FieldVarNode(){ delete expr; }
|
||||
void semant( Environ *e );
|
||||
TNode *translate( Codegen *g );
|
||||
struct FieldVarNode : public VarNode {
|
||||
ExprNode* expr;
|
||||
string ident, tag;
|
||||
Decl* sem_field;
|
||||
FieldVarNode(ExprNode* e, const string& i, const string& t) : expr(e), ident(i), tag(t) {}
|
||||
~FieldVarNode()
|
||||
{
|
||||
delete expr;
|
||||
}
|
||||
void semant(Environ* e);
|
||||
TNode* translate(Codegen* g);
|
||||
};
|
||||
|
||||
struct VectorVarNode : public VarNode{
|
||||
ExprNode *expr;
|
||||
ExprSeqNode *exprs;
|
||||
VectorType *vec_type;
|
||||
VectorVarNode( ExprNode *e,ExprSeqNode *es ):expr(e),exprs(es){}
|
||||
~VectorVarNode(){ delete expr;delete exprs; }
|
||||
void semant( Environ *e );
|
||||
TNode *translate( Codegen *g );
|
||||
struct VectorVarNode : public VarNode {
|
||||
ExprNode* expr;
|
||||
ExprSeqNode* exprs;
|
||||
VectorType* vec_type;
|
||||
VectorVarNode(ExprNode* e, ExprSeqNode* es) : expr(e), exprs(es) {}
|
||||
~VectorVarNode()
|
||||
{
|
||||
delete expr;
|
||||
delete exprs;
|
||||
}
|
||||
void semant(Environ* e);
|
||||
TNode* translate(Codegen* g);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user