diff --git a/Objects/LLang.l b/Objects/LLang.l index 26d9121..3f2bef1 100644 --- a/Objects/LLang.l +++ b/Objects/LLang.l @@ -17,13 +17,26 @@ ws [ \t]+ digits [0-9] intnum (0|[1-9]+{digits}*) floatnum (0|[1-9]+{digits}*)\.?{digits}* -STRING \"(\\.|[^"\\])*\" +STRING \"(\\.|[^"\\\n])*\" true True false False none None VAR [_]*[a-zA-Z][a-zA-Z0-9_]* EXIT exit[\(][\)] %% +> {return GT;} +>= {return GE;} +\< {return LT;} +\<= {return LE;} +== {return EQ;} +!= {return NE;} +not {return NOT;} +or {return OR;} +and {return AND;} +if {return IF;} +while {return WHILE;} +else {return ELSE;} +print {return PRINT;} {true} { yylval.sym = install("",object,(LLObject*)LLBool_Make(1)); return object;} diff --git a/Objects/LLang.y b/Objects/LLang.y index 99915d1..4a9aeda 100644 --- a/Objects/LLang.y +++ b/Objects/LLang.y @@ -1,12 +1,12 @@ %{ #include #include "Lala.h" +#include "vm.h" #include "abstract.h" #include "Symbol.h" extern void *code(Inst); #define code2(c1,c2) code(c1); code(c2); #define code3(c1,c2,c3) code(c1); code(c2); code(c3); - void execerror(char *s, char *t); void yyerror (char *s); int yylex (); @@ -22,19 +22,25 @@ int readfile = 0; Symbol *sym; Inst *inst; } -%token object VAR BLTIN INDEF EXIT -%type arraylist initarray +%token object VAR BLTIN INDEF EXIT IF ELSE PRINT WHILE +%type arraylist initarray asgn exp stmt stmtlist cond if end while %right '=' +%left OR +%left AND +%left GT GE LT LE EQ NE %left '+' '-' %left '*' '/' -%left UNARYMINUS +%left UNARYMINUS NOT +%nonassoc LOWER_THAN_ELSE +%nonassoc ELSE %% list: | list'\n' | list asgn '\n' {code2((Inst)pop,STOP);return 1;} | list exp '\n' { code2(print,STOP);return 1;} | list error '\n' {initcode();printf(">>> ");yyerrok;} + | list stmt '\n' {code(STOP);return 1;} ; initarray: {code(makeArray);} ; @@ -45,6 +51,35 @@ arraylist: arraylist','arraylist {} asgn: VAR '=' exp {code3(varpush,(Inst)$1,assign);} | exp '[' exp ']' '=' exp {code(ChangeValue);} ; +stmt: exp {code((Inst)pop);} + | PRINT exp { code(print); $$ = $2;} + | while cond stmt end { + ($1)[1] = (Inst)$3; + ($1)[2] = (Inst)$4; + } + | if cond stmt end %prec LOWER_THAN_ELSE{ + ($1)[1] = (Inst)$3; + ($1)[3] = (Inst)$4; + } + | if cond stmt end ELSE stmt end { + ($1)[1] = (Inst)$3; + ($1)[2] = (Inst)$6; + ($1)[3] = (Inst)$7; + } + | '{' stmtlist '}' {printf("...");$$=$2;} +; +cond: exp {code(STOP);$$=$1;} +; +if: IF {$$=code(ifcode);code3(STOP,STOP,STOP);} + ; +while: WHILE {$$= code3(whilecode,STOP,STOP);} + ; +end: '\n'{code(STOP);$$=progp;} + ; +stmtlist: {$$=progp;} + | stmtlist '\n' {printf("... ");} + | stmtlist stmt +; exp: object { code2(constpush,(Inst)$1);} | VAR {code3(varpush,(Inst)$1,eval);} | asgn @@ -55,6 +90,15 @@ exp: object { code2(constpush,(Inst)$1);} | '(' exp ')' { } |BLTIN '(' exp ')' {code2(bltin,(Inst)$1->u.ptr);} |'-' exp %prec UNARYMINUS {code(negate);} + | exp GT exp {code(gt);} + | exp GE exp {code(ge);} + | exp LT exp {code(lt);} + | exp LE exp {code(le);} + | exp EQ exp {code(eq);} + | exp NE exp {code(ne);} + | exp AND exp {code(and);} + | exp OR exp {code(or);} + | NOT exp {$$=$2;code(not);} | EXIT {exit(0);} | initarray '['arraylist']' {code(STOP);} | exp '[' exp ']' {code(aArray);} @@ -75,7 +119,7 @@ int main (int argc, char *argv[]){ progname=argv[0]; init(); if(argc==1){ - printf("Lala Lang v1.3 \n[GCC 8.2.1 20181127]\n"); + printf("Lala Lang v1.4 \n[GCC 8.2.1 20181127]\n"); setjmp(begin); printf(">>> "); for(initcode(); yyparse (); initcode()){ diff --git a/Objects/abstract.c b/Objects/abstract.c index d5dd894..b4b72c8 100644 --- a/Objects/abstract.c +++ b/Objects/abstract.c @@ -194,3 +194,91 @@ int LL_FUNC_PRINT(LLObject* o,char* end){ } return 0; } +double LL_CONDITION_EVAL(LLObject* o){ + double result = 0; + if(o==NULL) + return result; + if(o->ob_type==LLBoolTypeObject){ + result = (double)((LLBoolObject*)o)->o_val; + } + if(o->ob_type==LLListTypeObject){ + result =(double) ((LLEntryListObject*)o)->len; + } + if(o->ob_type==LLIntTypeObject){ + result =(double) ((LLIntObject*)o)->o_val; + } + if(o->ob_type==LLFloatTypeObject){ + result = (((LLFloatObject*)o)->o_val); + } + if(o->ob_type==LLStringTypeObject){ + result = (double)((LLStringObject*)o)->len; + } + return result; +} +LLObject* LL_FUNC_GT(LLObject* a,LLObject* b){ + int r1,r2; + if((a->ob_type!=b->ob_type)&&((a->ob_type == LLIntTypeObject || a->ob_type == LLFloatTypeObject ) && (b->ob_type == LLIntTypeObject || b->ob_type == LLFloatTypeObject))) + execerror("No se puede comparar!", NULL); + r1 = LL_CONDITION_EVAL(a); + r2 = LL_CONDITION_EVAL(b); + return (LLObject*)LLBool_Make(r1>r2); +} +LLObject* LL_FUNC_LT(LLObject*a,LLObject*b){ + int r1,r2; + if((a->ob_type!=b->ob_type)&&((a->ob_type == LLIntTypeObject || a->ob_type == LLFloatTypeObject ) && (b->ob_type == LLIntTypeObject || b->ob_type == LLFloatTypeObject))) + execerror("No se puede comparar!", NULL); + r1 = LL_CONDITION_EVAL(a); + r2 = LL_CONDITION_EVAL(b); + return (LLObject*)LLBool_Make(r1ob_type!=b->ob_type)&&((a->ob_type == LLIntTypeObject || a->ob_type == LLFloatTypeObject ) && (b->ob_type == LLIntTypeObject || b->ob_type == LLFloatTypeObject))) + execerror("No se puede comparar!", NULL); + r1 = LL_CONDITION_EVAL(a); + r2 = LL_CONDITION_EVAL(b); + return (LLObject*)LLBool_Make(r1>=r2); +} +LLObject* LL_FUNC_LE(LLObject*a,LLObject*b){ + int r1,r2; + if((a->ob_type!=b->ob_type)&&((a->ob_type == LLIntTypeObject || a->ob_type == LLFloatTypeObject ) && (b->ob_type == LLIntTypeObject || b->ob_type == LLFloatTypeObject))) + execerror("No se puede comparar!", NULL); + r1 = LL_CONDITION_EVAL(a); + r2 = LL_CONDITION_EVAL(b); + return (LLObject*)LLBool_Make(r1<=r2); +} +LLObject* LL_FUNC_EQ(LLObject*a,LLObject*b){ + int r1,r2; + if((a->ob_type!=b->ob_type)&&((a->ob_type == LLIntTypeObject || a->ob_type == LLFloatTypeObject ) && (b->ob_type == LLIntTypeObject || b->ob_type == LLFloatTypeObject))) + execerror("No se puede comparar!", NULL); + if(a->ob_type==LLStringTypeObject && b->ob_type==LLStringTypeObject){ + return (LLObject*)LLBool_Make(LLString_EQ(a,b)); + } + r1 = LL_CONDITION_EVAL(a); + r2 = LL_CONDITION_EVAL(b); + return (LLObject*)LLBool_Make(r1==r2); +} +LLObject* LL_FUNC_NE(LLObject*a,LLObject*b){ + if(a->ob_type!=b->ob_type){ + return (LLObject*)LLBool_Make(1); + } + LLBoolObject* r = (LLBoolObject*)LL_FUNC_EQ(a,b); + r->o_val = !(r->o_val); + return (LLObject*)r; +} +LLObject* LL_FUNC_AND(LLObject*a,LLObject*b){ + return (LLObject*)LLBool_Make(LL_CONDITION_EVAL(a)&&LL_CONDITION_EVAL(b)); +} +LLObject* LL_FUNC_OR(LLObject*a,LLObject*b){ + return (LLObject*)LLBool_Make(LL_CONDITION_EVAL(a)||LL_CONDITION_EVAL(b)); +} +LLObject* LL_FUNC_NOT(LLObject*a){ + return (LLObject*)LLBool_Make(!LL_CONDITION_EVAL(a)); +} +LLObject* LL_FUNC_LEN(LLObject* a){ + if(a->ob_type==LLListTypeObject) + return (LLObject*) LLInt_Make(((LLEntryListObject*)a)->len); + if(a->ob_type==LLStringTypeObject) + return (LLObject*) LLInt_Make(((LLStringObject*)a)->len); + execerror("BLINT 'len' no implementado", NULL); +} \ No newline at end of file diff --git a/Objects/init.c b/Objects/init.c index 7ab7387..f3da2d5 100644 --- a/Objects/init.c +++ b/Objects/init.c @@ -1,5 +1,16 @@ #include "Lala.h" +#include "abstract.h" +#include "Symbol.h" +#include "y.tab.h" +static struct { /* Predefinidos */ + char *name; + LLObject* (*func)(); +} builtins[] = { + "len", LL_FUNC_LEN, + 0, 0 +}; void init(){ + Symbol *s; LLIntTypeObject = calloc(1,sizeof(LLTypeObject)); LLStringTypeObject = calloc(1,sizeof(LLTypeObject)); LLListTypeObject = calloc(1,sizeof(LLTypeObject)); @@ -25,5 +36,10 @@ void init(){ c = malloc(sizeof(char)*14); strcpy(c,"\0"); LLNoneTypeObject->name = c; + + for (int i = 0; builtins[i].name; i++) { + s = install(builtins[i].name, BLTIN, (LLObject*)LLNone_Make()); + s->u.ptr = builtins[i].func; + } return; } \ No newline at end of file diff --git a/Objects/listObject.c b/Objects/listObject.c index 996c695..b3997bd 100644 --- a/Objects/listObject.c +++ b/Objects/listObject.c @@ -93,8 +93,10 @@ LLEntryListObject* LLList_getrange(LLEntryListObject* e,int* pos1,int* pos2){ return NULL; } } - if(pos1 !=0 && pos2!=0 && *pos1==*pos2) - return 0; + //if(pos1 !=0 && pos2!=0 && *pos1==*pos2) + //return 0; + if(start==end) + return 0; while(start->next!=end){ aux = LLList_append(aux,start->o); start = start->next; diff --git a/Objects/stringObject.c b/Objects/stringObject.c index ebb26a8..210a63f 100644 --- a/Objects/stringObject.c +++ b/Objects/stringObject.c @@ -49,3 +49,6 @@ LLObject* LLString_MUL(LLObject* s,LLObject* i){ cad[k+1]='\0'; return (LLObject*)LLString_Make(cad); } +int LLString_EQ(LLObject*a,LLObject*b){ + return strcmp(((LLStringObject*)a)->o_sval,((LLStringObject*)b)->o_sval)==0; +} \ No newline at end of file diff --git a/Objects/vm.c b/Objects/vm.c index 1d001c4..e6d5994 100644 --- a/Objects/vm.c +++ b/Objects/vm.c @@ -1,8 +1,5 @@ -#include "abstract.h" -#include "Symbol.h" -#include "Lala.h" +#include "vm.h" #include "y.tab.h" - extern void execerror(char *s, char *t); #define NSTACK 256 static Datum stack[NSTACK]; /* la pila */ @@ -166,6 +163,103 @@ void emptypush(){ d.val = 0; push(d); } + +void ifcode(){ + Datum d; + Inst *savepc = pc; /* parte then */ + execute(savepc+3); /* condición */ + d = pop(); + if(LL_CONDITION_EVAL(d.val)) + execute(*((Inst **)(savepc))); + else if(*((Inst **)(savepc+1))) /* ¿parte else? */ + execute(*(( Inst **) (savepc+1))); + pc = *((Inst **)(savepc+2)); /* siguiente proposición */ +} + +void whilecode(){ + Datum d; + Inst *savepc = pc; + execute(savepc+2); + d = pop(); + while(LL_CONDITION_EVAL(d.val)){ + execute(*((Inst **)(savepc))); + execute(savepc+2); + d = pop(); + } + pc = *((Inst **)(savepc+1)); +} + +void gt() { + Datum d1, d2; + d2 = pop(); + d1 = pop(); + d1.val = LL_FUNC_GT(d1.val,d2.val); + push(d1); +} + +void lt(){ + Datum d1, d2; + d2 = pop(); + d1 = pop(); + d1.val = LL_FUNC_LT(d1.val,d2.val); + push(d1); +} + +void ge( ) { + Datum d1, d2; + d2 = pop(); + d1 = pop(); + d1.val = LL_FUNC_GE(d1.val,d2.val); + push(d1) ; +} + +void le() { + Datum d1, d2; + d2 = pop(); + d1 = pop(); + d1.val = LL_FUNC_LE(d1.val,d2.val); + push(d1); +} + +void eq( ) { + Datum d1, d2; + d2 = pop(); + d1 = pop(); + d1.val =LL_FUNC_EQ(d1.val,d2.val); + push(d1); +} + +void ne(){ + Datum d1, d2; + d2 = pop(); + d1 = pop(); + d1.val = LL_FUNC_NE(d1.val,d2.val); + push(d1); +} + +void and(){ + Datum d1, d2; + d2 = pop(); + d1 = pop(); + d1.val = LL_FUNC_AND(d1.val,d2.val); + push(d1); +} + +void or(){ + Datum d1, d2; + d2 = pop(); + d1 = pop(); + d1.val = LL_FUNC_OR(d1.val,d2.val); + push(d1); +} + +void not( ){ + Datum d; + d = pop(); + d.val = LL_FUNC_NOT(d.val); + push(d); +} + Inst *code(Inst f) /* instalar una instrucción u operando */ { Inst *oprogp = progp; diff --git a/include/Symbol.h b/include/Symbol.h index 936fbf5..c1501c1 100644 --- a/include/Symbol.h +++ b/include/Symbol.h @@ -17,20 +17,5 @@ typedef struct Symbol { } Symbol; Symbol *install(char *s,int t, LLObject*), *lookup(char *s); - -typedef union Datum { /* tipo de la pila del intérprete */ - LLObject* val; - Symbol *sym; } Datum; - -extern Datum pop(); - -typedef void (*Inst)(); /* instrucción de máquina */ - -#define STOP (Inst) 0 -extern Inst prog[]; - -extern void eval(), addo(), subo(), mulo(), divo(),negate(); -extern void assign(), bltin(), varpush(), constpush(), print(),makeArray(),execute(Inst* p); -extern void aArray(),ChangeValue(),getSubArray(),emptypush(); - +typedef void (*Inst)(); #endif diff --git a/include/abstract.h b/include/abstract.h index ab387c2..65cd6ee 100644 --- a/include/abstract.h +++ b/include/abstract.h @@ -12,5 +12,16 @@ LLObject* LL_FUNC_AACCESS(LLObject*,LLObject*); int LL_FUNC_PRINT(LLObject*,char*); LLObject* LL_FUNC_AREPLACE(LLObject*,LLObject*,LLObject*); LLObject* LL_FUNC_GETSUBARRAY(LLObject*,LLObject*,LLObject*); +double LL_CONDITION_EVAL(LLObject*); +LLObject* LL_FUNC_GT(LLObject*,LLObject*); +LLObject* LL_FUNC_LT(LLObject*,LLObject*); +LLObject* LL_FUNC_GE(LLObject*,LLObject*); +LLObject* LL_FUNC_LE(LLObject*,LLObject*); +LLObject* LL_FUNC_EQ(LLObject*,LLObject*); +LLObject* LL_FUNC_NE(LLObject*,LLObject*); +LLObject* LL_FUNC_AND(LLObject*,LLObject*); +LLObject* LL_FUNC_OR(LLObject*,LLObject*); +LLObject* LL_FUNC_NOT(LLObject*); +LLObject* LL_FUNC_LEN(LLObject*); #define LL_NOT_IMPLEMENTED 0 #endif diff --git a/include/stringObject.h b/include/stringObject.h index 55663da..d2018da 100644 --- a/include/stringObject.h +++ b/include/stringObject.h @@ -15,4 +15,5 @@ LLObject* LLString_CAT(LLObject*,LLObject*); LLObject* LLString_String(LLObject*); LLObject* LLString_MUL(LLObject*,LLObject*); + int LLString_EQ(LLObject*,LLObject*); #endif diff --git a/include/vm.h b/include/vm.h new file mode 100644 index 0000000..104d951 --- /dev/null +++ b/include/vm.h @@ -0,0 +1,22 @@ +#ifndef __VM_H__ +#define __VM_H__ + +#include "Symbol.h" +#include "abstract.h" +#include "Lala.h" +typedef union Datum { /* tipo de la pila del intérprete */ + LLObject* val; + Symbol *sym; } Datum; + +extern Datum pop(); + +typedef void (*Inst)(); /* instrucción de máquina */ + +#define STOP (Inst) 0 +extern Inst prog[]; + +void eval(), addo(), subo(), mulo(), divo(),negate(); +void assign(), bltin(), varpush(), constpush(), print(),makeArray(),execute(Inst* p); +void aArray(),ChangeValue(),getSubArray(),emptypush(),ifcode(),whilecode(); +void gt(),ge(),lt(),le(),eq(),ne(),and(),or(),not(); +#endif \ No newline at end of file