Index: dtype.c =================================================================== RCS file: /home/danw/nawm/repository/nawm/dtype.c,v retrieving revision 1.3 diff -c -r1.3 dtype.c *** dtype.c 1999/11/26 20:32:54 1.3 --- dtype.c 1999/11/27 15:53:04 *************** *** 24,36 **** void inittypes(void) { ! nexttag = 5; typenames = xmalloc(nexttag * sizeof(char *)); typenames[0] = "void"; typenames[T_INT] = "int"; typenames[T_STR] = "string"; typenames[T_WIN] = "window"; - typenames[T_ARRAY] = NULL; } int newtype(char *name) --- 24,36 ---- void inittypes(void) { ! nexttag = T_NEXT; typenames = xmalloc(nexttag * sizeof(char *)); + memset(typenames, 0, nexttag * sizeof(char *)); typenames[0] = "void"; typenames[T_INT] = "int"; typenames[T_STR] = "string"; typenames[T_WIN] = "window"; } int newtype(char *name) *************** *** 66,71 **** --- 66,73 ---- } + /* Typecasts */ + static int ncasts, castssize; struct cast { dtype from, to; *************** *** 94,97 **** --- 96,128 ---- return casts[i].func; } return NULL; + } + + + /* Class/struct types */ + + int scopessize; + lexscope **scopes; + + void define_dtype_scope(dtype type, lexscope *scope) + { + if (type >= scopessize) + { + int oldsize = scopessize; + + while (type >= scopessize) + scopessize = 2 * (scopessize + 1); + scopes = xrealloc(scopes, scopessize * sizeof(lexscope *)); + memset(scopes + oldsize, 0, (scopessize - oldsize) * sizeof(lexscope *)); + } + + scopes[type] = scope; + } + + lexscope *lookup_dtype_scope(dtype type) + { + if (type < scopessize) + return scopes[type]; + else + return NULL; } Index: lang.h =================================================================== RCS file: /home/danw/nawm/repository/nawm/lang.h,v retrieving revision 1.25 diff -c -r1.25 lang.h *** lang.h 1999/11/26 22:03:52 1.25 --- lang.h 1999/11/27 15:48:32 *************** *** 22,27 **** --- 22,29 ---- #define T_WIN 2 #define T_STR 3 #define T_ARRAY 4 + #define T_CLASS 5 + #define T_NEXT 6 #define is_simple_type(t) (t < 4) #define is_atomic_type(t) (t < 3) *************** *** 71,76 **** --- 73,85 ---- void *data; struct _varbinding *next; } varbinding; + + typedef struct _lexscope { + struct _lexscope *parent; + int numvars; + varbinding *vars; + dtype *vtypes; + } lexscope; typedef struct _arrayiter { int ind; Index: lexer.l =================================================================== RCS file: /home/danw/nawm/repository/nawm/lexer.l,v retrieving revision 1.31 diff -c -r1.31 lexer.l *** lexer.l 1999/11/26 22:03:53 1.31 --- lexer.l 1999/11/28 02:23:22 *************** *** 43,54 **** int kind, lineno; - typedef struct _lexscope { - struct _lexscope *parent; - int numvars; - varbinding *vars; - dtype *vtypes; - } lexscope; static lexscope *scopestack; %} --- 43,48 ---- *************** *** 65,70 **** --- 59,67 ---- mode { return MODE; } + class { return CLASS; } + new { return NEW; } + int { yylval.i = T_INT; return DTYPE; } string { yylval.i = T_STR; return DTYPE; } window { yylval.i = T_WIN; return DTYPE; } *************** *** 90,104 **** return { return RETURN; } del { return DEL; } ! [A-Za-z_][A-Za-z_0-9]* { yylval.n = lookup(yytext, &kind, 0); ! if (yylval.n) ! return kind; ! else ! { ! yylval.s = xstrdup(yytext); ! return SYM; ! } ! } [0-9]+ { yylval.i = atoi(yytext); return NUM; } \"([^"\\]|\\.)*\" { yylval.s = process_string(yytext); return STR; } --- 87,93 ---- return { return RETURN; } del { return DEL; } ! [A-Za-z_][A-Za-z_0-9]* { yylval.s = xstrdup(yytext); return SYM; } [0-9]+ { yylval.i = atoi(yytext); return NUM; } \"([^"\\]|\\.)*\" { yylval.s = process_string(yytext); return STR; } *************** *** 127,132 **** --- 116,122 ---- "." { return '.'; } "," { return ','; } ";" { return ';'; } + ":" { return ':'; } [ \t]* { ; } #.*$ { ; } *************** *** 365,377 **** scopestack->vars = var; } ! void *lookup(char *name, int *type, int norecurse) { - lexscope *scope; varbinding *b; void *ans; ! for (scope = scopestack; scope; scope = scope->parent) { for (b = scope->vars; b; b = b->next) { --- 355,366 ---- scopestack->vars = var; } ! void *lookup_in_scope(char *name, int *type, lexscope *scope, int norecurse) { varbinding *b; void *ans; ! for (; scope; scope = scope->parent) { for (b = scope->vars; b; b = b->next) { *************** *** 385,390 **** --- 374,384 ---- break; } return NULL; + } + + void *lookup(char *name, int *type, int norecurse) + { + return lookup_in_scope(name, type, scopestack, norecurse); } char *nameof(void *data) Index: parser.y =================================================================== RCS file: /home/danw/nawm/repository/nawm/parser.y,v retrieving revision 1.32 diff -c -r1.32 parser.y *** parser.y 1999/11/26 22:03:54 1.32 --- parser.y 1999/11/28 02:42:46 *************** *** 67,77 **** dtype t; } ! %token MODE INCLUDE OPTION BEGIN_ END COMMAND FUNCTION %token KEYPRESS KEYRELEASE BUTTONPRESS BUTTONRELEASE MOTION ENTER LEAVE %token IF ELSE FOR IN WHILE DO BREAK CONTINUE RETURN DEL %token ASSIGNOP ADDOP MULTOP COMPOP BOOLOP UNOP SUBSCRIPT ELEMENT ! %token '(' ')' '[' ']' '{' '}' ',' ';' '.' %token NUM DTYPE %token VAR %token FUN CMD --- 67,77 ---- dtype t; } ! %token MODE INCLUDE OPTION BEGIN_ END COMMAND FUNCTION CLASS NEW %token KEYPRESS KEYRELEASE BUTTONPRESS BUTTONRELEASE MOTION ENTER LEAVE %token IF ELSE FOR IN WHILE DO BREAK CONTINUE RETURN DEL %token ASSIGNOP ADDOP MULTOP COMPOP BOOLOP UNOP SUBSCRIPT ELEMENT ! %token '(' ')' '[' ']' '{' '}' ',' ';' ':' '.' %token NUM DTYPE %token VAR %token FUN CMD *************** *** 82,90 **** %type bool_expr comp_expr memb_expr add_expr mult_expr unary_expr %type primary_expr lvalue subscript_expr %type key button ! %type type primitivetype %type binddecl modebody ! %type opt_string sym %% nawmrc : decls --- 82,90 ---- %type bool_expr comp_expr memb_expr add_expr mult_expr unary_expr %type primary_expr lvalue subscript_expr %type key button ! %type type primitivetype parenttype %type binddecl modebody ! %type opt_string %% nawmrc : decls *************** *** 98,103 **** --- 98,104 ---- decl : specdecl | modedecl + | classdecl | vardecl | fundecl | binddecl { add_to_anymode($1); } *************** *** 130,143 **** primitivetype : DTYPE { $$ = (dtype)$1; } ; ! sym : SYM ! | VAR { $$ = xstrdup(yytext); } ! | FUN { $$ = xstrdup(yytext); } ! | CMD { $$ = xstrdup(yytext); } ! ; ! ! syms1 : sym { $$ = mknode(0, 0, 1, $1); } ! | syms1 ',' sym { tmp = mknode(0, 0, 1, $3); $$ = chain(tmp, $1); } | error { die("while looking for a symbol name."); } ; --- 131,138 ---- primitivetype : DTYPE { $$ = (dtype)$1; } ; ! syms1 : SYM { $$ = mknode(0, 0, 1, $1); } ! | syms1 ',' SYM { tmp = mknode(0, 0, 1, $3); $$ = chain(tmp, $1); } | error { die("while looking for a symbol name."); } ; *************** *** 145,150 **** --- 140,157 ---- | syms1 { $$ = $1; } ; + classdecl : CLASS SYM parenttype '{' classbody '}' { defclass($2, $3); } + ; + + parenttype : { $$ = 0; } + | ':' DTYPE { $$ = $2; } + ; + + classbody : + | classbody vardecl + | classbody fundecl + ; + fundecl : COMMAND SYM syms { start_fundecl(0, $2); pushlexscope(1); } '{' vardecls commands '}' { finish_fundecl($2, $3, reverse($7)); } | FUNCTION type SYM '(' syms ')' { start_fundecl($2, $3); pushlexscope(1); } '{' vardecls commands '}' { finish_fundecl($3, $5, reverse($10)); } ; *************** *** 184,190 **** | commands1 command { $$ = chain($2, $1); } ; ! command : CMD exprs ';' { $$ = apply_check(CMD, $1, $2); } | IF '(' expr ')' command { $$ = mknode(IF, 0, 3, typecheck($3, T_INT), $5, NULL); } | IF '(' expr ')' command ELSE command { $$ = mknode(IF, 0, 3, typecheck($3, T_INT), $5, $7); } | FOR '(' forexpr ')' command { $$ = mknode(FOR, 0, 2, $3, $5); } --- 191,197 ---- | commands1 command { $$ = chain($2, $1); } ; ! command : SYM exprs ';' { $$ = apply_check(CMD, $1, $2); } | IF '(' expr ')' command { $$ = mknode(IF, 0, 3, typecheck($3, T_INT), $5, NULL); } | IF '(' expr ')' command ELSE command { $$ = mknode(IF, 0, 3, typecheck($3, T_INT), $5, $7); } | FOR '(' forexpr ')' command { $$ = mknode(FOR, 0, 2, $3, $5); } *************** *** 199,205 **** | error ';' { die("while parsing commands."); } ; ! forexpr : VAR IN expr { arraycheck($3); $$ = mknode(IN, 0, 2, typecheck(mknode(VAR, $1->type, 1, $1), array_basetype($3->etype)), $3); } | expr ';' expr ';' expr { $$ = mknode(FOR, 0, 3, $1, typecheck($3, T_INT), $5); } ; --- 206,212 ---- | error ';' { die("while parsing commands."); } ; ! forexpr : SYM IN expr { arraycheck($3); $$ = mknode(IN, 0, 2, typecheck(lookup_var($1), array_basetype($3->etype)), $3); } | expr ';' expr ';' expr { $$ = mknode(FOR, 0, 3, $1, typecheck($3, T_INT), $5); } ; *************** *** 220,227 **** | lvalue ASSIGNOP expr { $$ = mknode($2, $1->etype, 2, $1, typecheck($3, $1->etype)); } ; ! lvalue : VAR { $$ = mknode(VAR, $1->type, 1, $1); } | subscript_expr '[' expr ']' { arraycheck($1); $$ = mknode(SUBSCRIPT, array_basetype($1->etype), 2, $1, typecheck($3, array_subtype($1->etype))); } ; bool_expr : comp_expr --- 227,235 ---- | lvalue ASSIGNOP expr { $$ = mknode($2, $1->etype, 2, $1, typecheck($3, $1->etype)); } ; ! lvalue : SYM { $$ = lookup_var($1); } | subscript_expr '[' expr ']' { arraycheck($1); $$ = mknode(SUBSCRIPT, array_basetype($1->etype), 2, $1, typecheck($3, array_subtype($1->etype))); } + | subscript_expr '.' SYM { $$ = lookup_sym($1->etype, $3); } ; bool_expr : comp_expr *************** *** 250,262 **** subscript_expr : primary_expr | subscript_expr '[' expr ']' { arraycheck($1); $$ = mknode(SUBSCRIPT, array_basetype($1->etype), 2, $1, typecheck($3, array_subtype($1->etype))); } ! | subscript_expr '.' sym { arraycheck($1); $$ = mknode(ELEMENT, T_INT, 2, $1, $3); } ; primary_expr : NUM { $$ = mknode(NUM, T_INT, 1, $1); } | STR { $$ = mknode(STR, T_STR, 1, $1); } ! | VAR { $$ = mknode(VAR, $1->type, 1, $1); } ! | FUN opt_args { $$ = apply_check(FUN, $1, $2); } | '(' expr ')' { $$ = $2; } ; --- 258,270 ---- subscript_expr : primary_expr | subscript_expr '[' expr ']' { arraycheck($1); $$ = mknode(SUBSCRIPT, array_basetype($1->etype), 2, $1, typecheck($3, array_subtype($1->etype))); } ! | subscript_expr '.' SYM { $$ = lookup_sym($1->etype, $3); } ! | subscript_expr '(' exprs ') { $$ = apply_check(FUN, $1, $3); } ; primary_expr : NUM { $$ = mknode(NUM, T_INT, 1, $1); } | STR { $$ = mknode(STR, T_STR, 1, $1); } ! | SYM { $$ = lookup_sym(0, $1); } | '(' expr ')' { $$ = $2; } ; *************** *** 509,514 **** --- 517,553 ---- die("Type mismatch: expected array type, got %s, at line %d.", typename(array->etype), lineno); } + } + + static node *lookup_sym(dtype scopetype, char *name) + { + int type; + void *data; + + if (scopetype) + data = lookup_in_scope(name, &type, lookup_dtype_scope(scopetype), 0); + else + data = lookup(name, &type, 0); + + if (!data) + die("Undefined symbol \"%s\" at line %d.", name, lineno); + free(name); + + if (type == VAR) + return mknode(VAR, ((variable *)data)->etype, 1, data); + else + return mknode(type, type, 1, data); + } + + static node *lookup_var(char *name) + { + node *n = lookup_sym(0, name); + if (n->type != VAR) + { + die("Symbol \"%s\" is wrong type: expected variable, " + "got function at line %d.", name); + } + return n; } static void parse_error(char *error)