git @ Cat's Eye Technologies Bhuna / rel_0_1
Initial import of Bhuna 0.1 sources. catseye 9 years ago
57 changed file(s) with 4683 addition(s) and 0 deletion(s). Raw diff Collapse all Expand all
0 Program ::= {Statement}.
1 Block ::= Statement | "{" {Statement} "}".
2 Statement ::= (Control | Command | Assignment | Block) [";"].
3
4 Control ::= "if" Expr<0> Block ["else" Block]
5 | "while" Expr<0> Block.
6
7 Command ::= VarExpr Expr<0> {"," Expr<0>}
8 Assignment ::= ["local"] VarExpr "=" Expr<0>.
9
10 Expr<N> ::= Expr<N+1> {Op<N> Expr<N+1>}.
11 Expr<4> ::= Primitive.
12
13 Op<0> ::= "&" | "|".
14 Op<1> ::= ">" | "<" | ">=" | "<=" | "=" | "!=".
15 Op<2> ::= "+" | "-".
16 Op<3> ::= "*" | "/" | "%".
17
18 Primitive ::= "(" Expr<0> ")"
19 | "!" Primitive
20 | VarExpr
21 | Block [[2]]
22 | FunName "(" [Expr<0> {"," Expr<0>}] ")"
23 | Literal.
24
25 Literal ::= "[" [Literal {"," Literal}] "]"
26 | <<symbol>> [[3]]
27 | <<number>>.
28
29 VarExpr ::= Var {"[" Expr<0> "]"}.
30 Var ::= <<symbol>>. [[4]]
31
32 Footnotes:
33
34 [[2]]: Only blocks enclosed in braces are valid here.
35 [[3]]: Must start with lowercase letter.
36 [[4]]: Must start with Uppercase letter.
0 Bottles = 99
1 if Bottles > 0 {
2 print Bottles, " bottles of beer on the wall,", EoL,
3 Bottles, " bottles of beer,", EoL,
4 "Take one down, pass it around,", EoL,
5 Bottles - 1, " bottles of beer on the wall.", EoL, EoL
6 Bottles = Bottles - 1
7 }
8
0 Bottles = 9999
1 while Bottles > 0 {
2 Print Bottles, " bottles of beer on the wall,", EoL,
3 Bottles, " bottles of beer,", EoL,
4 "Take one down, pass it around,", EoL,
5 Bottles - 1, " bottles of beer on the wall.", EoL, EoL
6 Bottles = Bottles - 1
7 }
8
0 #!/usr/local/bin/lua
1
2 bottles = 9999
3 while (bottles > 0) do
4 print(bottles, "bottles of beer on the wall,")
5 print(bottles, "bottles of beer,")
6 print("Take none down, pass none around,")
7 print(bottles - 1, "bottles of beer on the wall.");
8 print("");
9 bottles = bottles - 1
10 end
0 #!/usr/bin/perl
1
2 $bottles = 9999;
3 while ($bottles > 0) {
4 print "$bottles bottles of beer on the wall,\n";
5 print "$bottles bottles of beer,\n";
6 print "Take none down, pass none around,\n";
7 $bottles = $bottles - 1;
8 print "$bottles bottles of beer on the wall.\n";
9 print "\n";
10 }
0 F = {
1 Print "hello from f", EoL
2 Print Arg, EoL
3 Print "goodbye from f", EoL
4 Return [119,123] // Index(Arg, 1)
5 }
6
7 G = F([1,2,3],[4,5,6])
8 Print G, EoL
9
0 G = {
1 Q = "hello"
2 F = {
3 Print Q
4 }
5 F
6 }
7
8 G
0 F = {
1 T = 123
2 Return { Return 17 }
3 }
4
5 Print F, EoL
6 Print F(), EoL
7 Print F()(), EoL
8 Print F()()(), EoL
0 F = {
1 Q = 17
2 Return { Return Q }
3 }
4 Print F()()
0 F = {
1 Level = Index(Arg, 1)
2 Print "Level is ", Level, EoL
3 Q = {
4 QLev = Index(Arg, 1)
5 Print "QLev is ", QLev, EoL
6 Print "(And Q thinks Level is ", Level, ")", EoL
7 if (QLev < 3)
8 Q QLev + 1
9 else
10 Print "This is as far as we go.", EoL
11 }
12 if Level < 3 {
13 F Level + 1
14 } else {
15 Print "At level three, woo!", EoL
16 Q(0)
17 }
18 }
19
20 F(0)
0 F = {
1 C = Index(Arg, 1)
2 C Index(Arg, 2)
3 C "cheese"
4 }
5
6 R = {
7 Print "R was called with ", Index(Arg, 1), EoL
8 }
9
10 F R, "Spam Spam Spam Spam wonderful Spam!"
11
0
1 Q = {}
2 P = {
3 Level = Arg[1]
4 if (Level > 0) {
5 Print "Calling Q at level ", Level, EoL
6 Q Level - 1
7 Print "Called Q, Exiting P at level ", Level, EoL
8 }
9 }
10 Q = {
11 Level = Arg.1
12 if (Level > 0) {
13 Print "Calling P at level ", Level, EoL
14 P Level - 1
15 Print "Called P, Exiting Q at level ", Level, EoL
16 }
17 }
18
19 P 10
0 F = {
1 Q = 17
2 G = {
3 Print "Q is ", Q, EoL
4 }
5 G;
6 Return G
7 }
8
9 G = F()
10 G;
11
12
0 F = {
1 Q = 17
2 G = {
3 Print "Q is ", Q, EoL
4 }
5 G;
6 Q = 23;
7 G;
8 Return G
9 }
10
11 G = F()
12 G;
13
14
0 F = 19
1
2 Foo = {
3 local F = 23
4 print F
5 }
6
7 Print F
8 Foo;
9 Print F
0 Foo = {
1 Print Arg
2 }
3
4 Foo 19, 23, 76;
0 Song = {
1 Bottles = 99
2
3 Sing = {
4 Print Bottles, " bottles of beer on the wall,", EoL,
5 Bottles, " bottles of beer,", EoL,
6 "Take none down, pass none around,", EoL,
7 Bottles, " bottles of beer on the wall.", EoL, EoL
8 }
9
10 while True Sing
11
12 }
13
14 Song
0 F = {
1 Q = 17
2 Return { Print Q }
3 }
4
5 while True {
6 G = F()
7 G;
8 }
9
0 Bottles = 99
1 while True {
2 Print Bottles, " bottles of beer on the wall,", EoL,
3 Bottles, " bottles of beer,", EoL,
4 "Take none down, pass none around,", EoL,
5 Bottles, " bottles of beer on the wall.", EoL, EoL
6 }
0 A = ["moe","larry","curly"]
1
2 B = Index(A, 1)
3
4 Print B
5
6 // B = [1,"hello","there"]
7 // Print A, EoL
8 // Print B, EoL
9 // B = A
10 // Print A, EoL
11 // Print B, EoL
12
0
1 F = {
2 Print "hello!"
3 }
4
5 G = {
6 Print "naff!"
7 }
8
9 H = G // does not dup the AST...
10 G = F // lost one ref to the AST...
11 F = G // my fears were unfounded
12
0 G = 3
1
2 R = {
3 if G > 0 {
4 G = G - 1
5 R
6 }
7 }
8
9 R
0
1 R = {
2 P = Arg[1]
3 Print "P is ", P, EoL
4 if (P > 0) R P - 1
5 Print "P is still ", P, EoL
6 }
7
8 R 2
0 A = 1
1 B = 2
2 A = B
3 // debug
4
0 local F = 100
1 while F > 20 {
2 local F = 10
3 print F
4 // global f = 3
5 }
6 print F
7
0 B = 100
1 Print B
2 B = B * 5
3 Print B
0 #include <stdio.h>
1
2 int main(int argc, char **argv)
3 {
4 int f = 100;
5
6 while (f > 20) {
7 int f = 10;
8 printf("%d", f);
9 }
10 printf("%d", f);
11
12 exit(0);
13 }
0 PROG= bhuna
1 SRCS= scan.c parse.c \
2 symbol.c ast.c \
3 mem.c \
4 list.c atom.c buffer.c closure.c dict.c value.c \
5 activation.c eval.c \
6 builtin.c \
7 main.c
8
9 CFLAGS+=-Wall -I/usr/local/include
10 .ifndef NODEBUG
11 CFLAGS+=-g -DDEBUG
12 .else
13 CFLAGS+=-DNDEBUG
14 .endif
15
16 NOMAN= y
17
18 # DESTDIR=/usr/local/sbin
19 strip: bhuna
20 strip bhuna
21 ls -lah bhuna
22 ls -la bhuna
23
24 .include <bsd.prog.mk>
0 #include <assert.h>
1 #include <stdlib.h>
2 #include <stdio.h>
3
4 #include "activation.h"
5
6 #include "mem.h"
7 #include "symbol.h"
8 #include "value.h"
9
10 #ifdef DEBUG
11 extern int trace_activations;
12 #endif
13
14 struct activation *
15 activation_new(struct symbol_table *stab, struct activation *enclosing)
16 {
17 struct activation *a;
18 struct symbol *sym;
19
20 a = bhuna_malloc(sizeof(struct activation));
21 a->alist = NULL;
22 activation_grab(enclosing);
23 a->enclosing = enclosing;
24 a->refcount = 1;
25
26 for (sym = stab->head; sym != NULL; sym = sym->next) {
27 struct alist *al;
28
29 al = bhuna_malloc(sizeof(struct alist));
30 al->next = a->alist;
31 al->sym = sym;
32 al->value = NULL;
33 a->alist = al;
34 }
35
36 #ifdef DEBUG
37 if (trace_activations > 1) {
38 printf("[ARC] created ");
39 activation_dump(a, -1);
40 printf("\n");
41 }
42 #endif
43
44 return(a);
45 }
46
47 void
48 activation_free(struct activation *a)
49 {
50 struct alist *next;
51
52 #ifdef DEBUG
53 if (trace_activations > 1) {
54 printf("[ARC] freeing ");
55 activation_dump(a, -1);
56 printf("\n");
57 }
58 #endif
59
60 assert(a->refcount == 0);
61 while (a->alist != NULL) {
62 next = a->alist->next;
63 value_release(a->alist->value);
64 bhuna_free(a->alist);
65 a->alist = next;
66 }
67 activation_release(a->enclosing);
68 bhuna_free(a);
69 }
70
71 /*** REFCOUNTERS ***/
72
73 void
74 activation_grab(struct activation *a)
75 {
76 if (a == NULL)
77 return;
78 a->refcount++;
79 #ifdef DEBUG
80 if (trace_activations > 1) {
81 printf("[ARC] ");
82 activation_dump(a, -1);
83 printf(" grabbed, refcount now %d\n", a->refcount);
84 }
85 #endif
86 }
87
88 void
89 activation_release(struct activation *a)
90 {
91 if (a == NULL)
92 return;
93 a->refcount--;
94 #ifdef DEBUG
95 if (trace_activations > 1) {
96 printf("[ARC] ");
97 activation_dump(a, -1);
98 printf(" released, refcount now %d\n", a->refcount);
99 }
100 #endif
101 if (a->refcount == 0)
102 activation_free(a);
103 }
104
105 static struct alist *
106 activation_find_sym(struct activation *a, struct symbol *sym)
107 {
108 struct alist *al;
109
110 for (al = a->alist; al != NULL; al = al->next) {
111 if (al->sym == sym)
112 return(al);
113 }
114
115 if (a->enclosing != NULL)
116 return(activation_find_sym(a->enclosing, sym));
117
118 return(NULL);
119 }
120
121 struct value *
122 activation_get_value(struct activation *a, struct symbol *sym)
123 {
124 struct alist *al;
125
126 al = activation_find_sym(a, sym);
127 assert(al != NULL);
128
129 return(al->value);
130 }
131
132 void
133 activation_set_value(struct activation *a, struct symbol *sym, struct value *v)
134 {
135 struct alist *al;
136
137 if ((al = activation_find_sym(a, sym)) == NULL) {
138 #ifdef DEBUG
139 if (trace_activations > 1) {
140 printf("WARNING: ");
141 symbol_dump(sym, 0);
142 printf(" (=");
143 value_print(v);
144 printf(") not found in ");
145 activation_dump(a, -1);
146 printf(", adding\n");
147 }
148 #endif
149
150 al = bhuna_malloc(sizeof(struct alist));
151 al->next = a->alist;
152 al->sym = sym;
153 al->value = NULL;
154 a->alist = al;
155 }
156
157 value_release(al->value);
158 value_grab(v);
159 al->value = v;
160 }
161
162 void
163 activation_dump(struct activation *a, int detail)
164 {
165 #ifdef DEBUG
166 struct alist *al;
167
168 printf("Activation/");
169 if (a == NULL) {
170 printf("(NULL)/");
171 return;
172 }
173 if (detail == -1) {
174 printf("%08lx", (unsigned long)a);
175 } else {
176 for (al = a->alist; al != NULL; al = al->next) {
177 symbol_dump(al->sym, 0);
178 if (detail) {
179 printf("=");
180 value_print(al->value);
181 }
182 printf(" ");
183 }
184 }
185 if (a->enclosing != NULL) {
186 printf(" --> ");
187 activation_dump(a->enclosing, detail);
188 }
189 printf("/");
190 #endif
191 }
0 struct symbol_table;
1 struct symbol;
2 struct value;
3
4 struct activation {
5 int refcount;
6 struct alist *alist;
7 struct activation *enclosing; /* lexically enclosing activation record */
8 };
9
10 struct alist {
11 struct alist *next;
12 struct symbol *sym;
13 struct value *value;
14 };
15
16
17 struct activation *activation_new(struct symbol_table *, struct activation *);
18 void activation_free(struct activation *);
19
20 void activation_grab(struct activation *);
21 void activation_release(struct activation *);
22
23 struct value *activation_get_value(struct activation *, struct symbol *);
24 void activation_set_value(struct activation *, struct symbol *, struct value *);
25
26 void activation_dump(struct activation *, int);
0 #include <stdio.h>
1 #include <stdlib.h>
2 #include <string.h>
3
4 #include "ast.h"
5 #include "list.h"
6 #include "symbol.h"
7 #include "value.h"
8
9 /***** constructors *****/
10
11 struct ast *
12 ast_new_sym(struct symbol *s)
13 {
14 struct ast *a;
15
16 a = malloc(sizeof(struct ast));
17 a->type = AST_SYM;
18
19 a->u.sym.sym = s;
20
21 return(a);
22 }
23
24 struct ast *
25 ast_new_value(struct value *v)
26 {
27 struct ast *a;
28
29 a = malloc(sizeof(struct ast));
30 a->type = AST_VALUE;
31
32 value_grab(v);
33 a->u.value.value = v;
34
35 return(a);
36 }
37
38 struct ast *
39 ast_new_scope(struct ast *body, struct symbol_table *local)
40 {
41 struct ast *a;
42
43 a = malloc(sizeof(struct ast));
44 a->type = AST_SCOPE;
45
46 a->u.scope.body = body;
47
48 a->u.scope.local = local;
49
50 return(a);
51 }
52
53 struct ast *
54 ast_new_apply(struct ast *fn, struct ast *args)
55 {
56 struct ast *a;
57
58 a = malloc(sizeof(struct ast));
59 a->type = AST_APPLY;
60
61 a->u.apply.left = fn;
62 a->u.apply.right = args;
63
64 return(a);
65 }
66
67 struct ast *
68 ast_new_arg(struct ast *left, struct ast *right)
69 {
70 struct ast *a;
71
72 a = malloc(sizeof(struct ast));
73 a->type = AST_ARG;
74
75 a->u.arg.left = left;
76 a->u.arg.right = right;
77
78 return(a);
79 }
80
81 struct ast *
82 ast_new_statement(struct ast *left, struct ast *right)
83 {
84 struct ast *a;
85
86 /*
87 if (left == NULL && right == NULL)
88 return(NULL);
89 if (left == NULL)
90 return(right);
91 if (right == NULL)
92 return(left);
93 */
94
95 a = malloc(sizeof(struct ast));
96 a->type = AST_STATEMENT;
97
98 a->u.statement.left = left;
99 a->u.statement.right = right;
100
101 return(a);
102 }
103
104 struct ast *
105 ast_new_assignment(struct ast *left, struct ast *right)
106 {
107 struct ast *a;
108
109 a = malloc(sizeof(struct ast));
110 a->type = AST_ASSIGNMENT;
111
112 a->u.assignment.left = left;
113 a->u.assignment.right = right;
114
115 return(a);
116 }
117
118 struct ast *
119 ast_new_conditional(struct ast *test, struct ast *yes, struct ast *no)
120 {
121 struct ast *a;
122
123 a = malloc(sizeof(struct ast));
124 a->type = AST_CONDITIONAL;
125
126 a->u.conditional.test = test;
127 a->u.conditional.yes = yes;
128 a->u.conditional.no = no;
129
130 return(a);
131 }
132
133 struct ast *
134 ast_new_while_loop(struct ast *test, struct ast *body)
135 {
136 struct ast *a;
137
138 a = malloc(sizeof(struct ast));
139 a->type = AST_WHILE_LOOP;
140
141 a->u.while_loop.test = test;
142 a->u.while_loop.body = body;
143
144 return(a);
145 }
146
147 void
148 ast_free(struct ast *a)
149 {
150 if (a == NULL) {
151 return;
152 }
153 switch (a->type) {
154 case AST_SYM:
155 break;
156 case AST_VALUE:
157 value_release(a->u.value.value);
158 break;
159 case AST_SCOPE:
160 ast_free(a->u.scope.body);
161 break;
162 case AST_APPLY:
163 ast_free(a->u.apply.left);
164 ast_free(a->u.apply.right);
165 break;
166 case AST_ARG:
167 ast_free(a->u.arg.left);
168 ast_free(a->u.arg.right);
169 break;
170 case AST_STATEMENT:
171 ast_free(a->u.statement.left);
172 ast_free(a->u.statement.right);
173 break;
174 case AST_ASSIGNMENT:
175 ast_free(a->u.assignment.left);
176 ast_free(a->u.assignment.right);
177 break;
178 case AST_CONDITIONAL:
179 ast_free(a->u.conditional.test);
180 ast_free(a->u.conditional.yes);
181 ast_free(a->u.conditional.no);
182 break;
183 case AST_WHILE_LOOP:
184 ast_free(a->u.while_loop.test);
185 ast_free(a->u.while_loop.body);
186 break;
187 }
188 free(a);
189 }
190
191 char *
192 ast_name(struct ast *a)
193 {
194 #ifdef DEBUG
195 if (a == NULL)
196 return("(null)");
197 switch (a->type) {
198 case AST_SYM:
199 return("AST_SYM");
200 case AST_VALUE:
201 return("AST_VALUE");
202 case AST_SCOPE:
203 return("AST_SCOPE");
204 case AST_APPLY:
205 return("AST_APPLY");
206 case AST_ARG:
207 return("AST_ARG");
208 case AST_STATEMENT:
209 return("AST_STATEMENT");
210 case AST_ASSIGNMENT:
211 return("AST_ASSIGNMENT");
212 case AST_CONDITIONAL:
213 return("AST_CONDITIONAL");
214 case AST_WHILE_LOOP:
215 return("AST_WHILE_LOOP");
216 }
217 #endif
218 return("AST_UNKNOWN??!?");
219 }
220
221 void
222 ast_dump(struct ast *a, int indent)
223 {
224 #ifdef DEBUG
225 int i;
226
227 if (a == NULL) {
228 return;
229 }
230 for (i = 0; i < indent; i++) printf(" ");
231 switch (a->type) {
232 case AST_SYM:
233 printf("symbol(");
234 symbol_dump(a->u.sym.sym, 0);
235 printf(")\n");
236 break;
237 case AST_VALUE:
238 printf("value(");
239 value_print(a->u.value.value);
240 printf(")\n");
241 break;
242 case AST_SCOPE:
243 printf("scope {\n");
244 symbol_table_dump(a->u.scope.local, 0);
245 /*symbol_table_dump(a->u.scope.trap, 0);*/
246 ast_dump(a->u.scope.body, indent + 1);
247 for (i = 0; i < indent; i++) printf(" "); printf("}\n");
248 break;
249 case AST_APPLY:
250 printf("apply {\n");
251 ast_dump(a->u.apply.left, indent + 1);
252 ast_dump(a->u.apply.right, indent + 1);
253 for (i = 0; i < indent; i++) printf(" "); printf("}\n");
254 break;
255 case AST_ARG:
256 printf("arg {\n");
257 ast_dump(a->u.arg.left, indent + 1);
258 ast_dump(a->u.arg.right, indent + 1);
259 for (i = 0; i < indent; i++) printf(" "); printf("}\n");
260 break;
261 case AST_STATEMENT:
262 printf("statement {\n");
263 ast_dump(a->u.statement.left, indent + 1);
264 ast_dump(a->u.statement.right, indent + 1);
265 for (i = 0; i < indent; i++) printf(" "); printf("}\n");
266 break;
267 case AST_ASSIGNMENT:
268 printf("assign {\n");
269 ast_dump(a->u.assignment.left, indent + 1);
270 ast_dump(a->u.assignment.right, indent + 1);
271 for (i = 0; i < indent; i++) printf(" "); printf("}\n");
272 break;
273 case AST_CONDITIONAL:
274 printf("conditional {\n");
275 ast_dump(a->u.conditional.test, indent + 1);
276 ast_dump(a->u.conditional.yes, indent + 1);
277 if (a->u.conditional.no != NULL)
278 ast_dump(a->u.conditional.no, indent + 1);
279 for (i = 0; i < indent; i++) printf(" "); printf("}\n");
280 break;
281 case AST_WHILE_LOOP:
282 printf("while {\n");
283 ast_dump(a->u.while_loop.test, indent + 1);
284 ast_dump(a->u.while_loop.body, indent + 1);
285 break;
286 }
287 #endif
288 }
0 #ifndef __AST_H_
1 #define __AST_H_
2
3 struct value;
4 struct symbol;
5 struct list;
6
7 struct ast_sym {
8 struct symbol *sym;
9 };
10
11 struct ast_value {
12 struct value *value;
13 };
14
15 struct ast_scope {
16 struct symbol_table *local;
17 struct ast *body;
18 };
19
20 struct ast_apply {
21 struct ast *left; /* ISA var(/...?) (fn/cmd) */
22 struct ast *right; /* ISA arg */
23 };
24
25 struct ast_arg {
26 struct ast *left; /* ISA arg/apply/var */
27 struct ast *right; /* ISA arg/apply/var */
28 };
29
30 struct ast_statement {
31 struct ast *left; /* ISA statement/apply */
32 struct ast *right; /* ISA statement/apply */
33 };
34
35 struct ast_assignment {
36 struct ast *left; /* ISA var */
37 struct ast *right; /* ISA apply/var */
38 };
39
40 struct ast_conditional {
41 struct ast *test; /* ISA apply/var */
42 struct ast *yes; /* ISA statement/apply */
43 struct ast *no; /* ISA statement/apply/NULL */
44 };
45
46 struct ast_while_loop {
47 struct ast *test; /* ISA apply/var */
48 struct ast *body; /* ISA statement/apply */
49 };
50
51 #define AST_SYM 1
52 #define AST_VALUE 2
53 #define AST_SCOPE 3
54 #define AST_APPLY 4
55 #define AST_ARG 5
56 #define AST_STATEMENT 6
57 #define AST_ASSIGNMENT 7
58 #define AST_CONDITIONAL 8
59 #define AST_WHILE_LOOP 9
60
61 union ast_union {
62 struct ast_sym sym;
63 struct ast_value value;
64 struct ast_scope scope;
65 struct ast_apply apply;
66 struct ast_arg arg;
67 struct ast_statement statement;
68 struct ast_assignment assignment;
69 struct ast_conditional conditional;
70 struct ast_while_loop while_loop;
71 };
72
73 struct ast {
74 int type;
75 union ast_union u;
76 };
77
78 struct ast *ast_new_sym(struct symbol *);
79 struct ast *ast_new_value(struct value *);
80 struct ast *ast_new_scope(struct ast *, struct symbol_table *);
81 struct ast *ast_new_apply(struct ast *, struct ast *);
82 struct ast *ast_new_arg(struct ast *, struct ast *);
83 struct ast *ast_new_statement(struct ast *, struct ast *);
84 struct ast *ast_new_assignment(struct ast *, struct ast *);
85 struct ast *ast_new_conditional(struct ast *, struct ast *, struct ast *);
86 struct ast *ast_new_while_loop(struct ast *, struct ast *);
87 void ast_free(struct ast *);
88
89 void ast_dump(struct ast *, int);
90 char *ast_name(struct ast *);
91
92 void ast_eval(struct ast *, struct value **);
93
94 #endif /* !__AST_H_ */
0 #include <string.h>
1 #include <stdlib.h>
2
3 #include "mem.h"
4 #include "atom.h"
5
6 static struct atom_entry *atom_entry_head = NULL;
7 static int next_atom = 0;
8
9 int
10 atom_resolve(char *lexeme)
11 {
12 struct atom_entry *ae;
13
14 /* find lexeme in atom table */
15 for (ae = atom_entry_head; ae != NULL; ae = ae->next) {
16 if (strcmp(ae->lexeme, lexeme) == 0)
17 return(ae->atom);
18 }
19 /* create new atom */
20 ae = bhuna_malloc(sizeof(struct atom_entry));
21 ae->next = atom_entry_head;
22 ae->lexeme = strdup(lexeme);
23 ae->atom = next_atom++;
24 atom_entry_head = ae;
25
26 return(ae->atom);
27 }
0 #ifndef __ATOM_H_
1 #define __ATOM_H_
2
3 struct atom_entry {
4 struct atom_entry *next;
5 char *lexeme;
6 int atom;
7 };
8
9 int atom_resolve(char *);
10
11 #endif /* !__ATOM_H_ */
0 /*
1 * Copyright (c) 2004 The DragonFly Project. All rights reserved.
2 *
3 * This code is derived from software contributed to The DragonFly Project
4 * by Chris Pressey <cpressey@catseye.mine.nu>.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in
14 * the documentation and/or other materials provided with the
15 * distribution.
16 * 3. Neither the name of The DragonFly Project nor the names of its
17 * contributors may be used to endorse or promote products derived
18 * from this software without specific, prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
26 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
28 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
30 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34 /*
35 * extbuf.c
36 * $Id: buffer.c,v 1.1 2004/07/21 19:52:35 cpressey Exp $
37 * Routines to manipulate extensible buffers.
38 *
39 * Aura buffers are buffers that attempt to automatically expand
40 * when more data is written to them than they can initially hold.
41 * In addition, each extensible buffer contains a cursor from which
42 * its contents may be incrementally scanned.
43 */
44
45 #include <err.h>
46 #include <stdarg.h>
47 #include <stdio.h>
48 #include <stdlib.h>
49 #include <string.h>
50 #include <sysexits.h>
51
52 #include "buffer.h"
53
54 /*
55 * Create a new extensible buffer with the given initial size.
56 */
57 struct aura_buffer *
58 aura_buffer_new(size_t size)
59 {
60 struct aura_buffer *e;
61
62 e = malloc(sizeof(struct aura_buffer));
63
64 e->len = 0;
65 e->size = size;
66 e->pos = 0;
67
68 e->buf = malloc(size);
69 e->buf[0] = '\0';
70
71 return(e);
72 }
73
74 /*
75 * Deallocate the memory used for an extensible buffer.
76 */
77 void
78 aura_buffer_free(struct aura_buffer *e)
79 {
80 if (e != NULL) {
81 if (e->buf != NULL)
82 free(e->buf);
83 free(e);
84 }
85 }
86
87 /*
88 * Return the underlying (static) buffer of an extensible buffer.
89 *
90 * NOTE that you should NEVER cache the returned pointer anywhere,
91 * as any further manipulation of the extensible buffer may cause
92 * it to be invalidated.
93 *
94 * ALSO NOTE that the buffer may contain embedded NULs, but will
95 * also be guaranteed to be NUL-terminated.
96 */
97 char *
98 aura_buffer_buf(struct aura_buffer *e)
99 {
100 return(e->buf);
101 }
102
103 /*
104 * Return the current length of the extensible buffer.
105 */
106 size_t
107 aura_buffer_len(struct aura_buffer *e)
108 {
109 return(e->len);
110 }
111
112 /*
113 * Return the current size of the extensible buffer. This is how
114 * big it's length may grow to before expanded.
115 */
116 size_t
117 aura_buffer_size(struct aura_buffer *e)
118 {
119 return(e->size);
120 }
121
122 /*
123 * Ensure that an extensible buffer's size is at least the given
124 * size. If it is not, it will be internally grown to that size.
125 * This does not affect the contents of the buffer in any way.
126 */
127 void
128 aura_buffer_ensure_size(struct aura_buffer *e, size_t size)
129 {
130 if (e->size >= size) return;
131 e->size = size;
132 if ((e->buf = realloc(e->buf, e->size)) == NULL) {
133 err(EX_UNAVAILABLE, "realloc()");
134 }
135 }
136
137 /*
138 * Set the contents of an extensible buffer from a regular (char *)
139 * buffer. The extensible buffer will grow if needed. Any existing
140 * contents of the extensible buffer are destroyed in this operation.
141 * Note that, because this requires that the length of the
142 * regular buffer be specified, it may safely contain NUL bytes.
143 */
144 void
145 aura_buffer_set(struct aura_buffer *e, char *buf, size_t length)
146 {
147 while ((length + 1) > e->size) {
148 e->size *= 2;
149 }
150 if ((e->buf = realloc(e->buf, e->size)) == NULL) {
151 err(EX_UNAVAILABLE, "realloc()");
152 }
153 memcpy(e->buf, buf, length);
154 e->len = length;
155 e->buf[e->len] = '\0';
156 }
157
158 /*
159 * Append the contents of a regular buffer to the end of the existing
160 * contents of an extensible buffer. The extensible buffer will grow
161 * if needed. Note that, because this requires that the length of the
162 * regular buffer be specified, it may safely contain NUL bytes.
163 */
164 void
165 aura_buffer_append(struct aura_buffer *e, char *buf, size_t length)
166 {
167 while (e->len + (length + 1) > e->size) {
168 e->size *= 2;
169 }
170 if ((e->buf = realloc(e->buf, e->size)) == NULL) {
171 err(EX_UNAVAILABLE, "realloc()");
172 }
173 memcpy(e->buf + e->len, buf, length);
174 e->len += length;
175 e->buf[e->len] = '\0';
176 }
177
178 /*
179 * Set the contents of an extensible buffer from an ASCIIZ string.
180 * This is identical to aura_buffer_set except that the length need not
181 * be specified, and the ASCIIZ string may not contain embedded NUL's.
182 */
183 void
184 aura_buffer_cpy(struct aura_buffer *e, char *s)
185 {
186 aura_buffer_set(e, s, strlen(s));
187 }
188
189 /*
190 * Append the contents of an ASCIIZ string to an extensible buffer.
191 * This is identical to aura_buffer_append except that the length need not
192 * be specified, and the ASCIIZ string may not contain embedded NUL's.
193 */
194 void
195 aura_buffer_cat(struct aura_buffer *e, char *s)
196 {
197 aura_buffer_append(e, s, strlen(s));
198 }
199
200 /*
201 * Append the entire contents of a text file to an extensible buffer.
202 */
203 int
204 aura_buffer_cat_file(struct aura_buffer *e, char *fmt, ...)
205 {
206 va_list args;
207 char *filename, line[1024];
208 FILE *f;
209
210 va_start(args, fmt);
211 vasprintf(&filename, fmt, args);
212 va_end(args);
213
214 if ((f = fopen(filename, "r")) == NULL)
215 return(0);
216
217 free(filename);
218
219 while (fgets(line, 1023, f) != NULL) {
220 aura_buffer_cat(e, line);
221 }
222
223 fclose(f);
224
225 return(1);
226 }
227
228 /*
229 * Append the entire output of a shell command to an extensible buffer.
230 */
231 int
232 aura_buffer_cat_pipe(struct aura_buffer *e, char *fmt, ...)
233 {
234 va_list args;
235 char *command, line[1024];
236 FILE *p;
237
238 va_start(args, fmt);
239 vasprintf(&command, fmt, args);
240 va_end(args);
241
242 if ((p = popen(command, "r")) == NULL)
243 return(0);
244
245 free(command);
246
247 while (fgets(line, 1023, p) != NULL) {
248 aura_buffer_cat(e, line);
249 }
250
251 pclose(p);
252
253 return(1);
254 }
255
256 /*** CURSORED FUNCTIONS ***/
257
258 /*
259 * Note that the cursor can be anywhere from the first character to
260 * one position _beyond_ the last character in the buffer.
261 */
262
263 int
264 aura_buffer_seek(struct aura_buffer *e, size_t pos)
265 {
266 if (pos <= e->size) {
267 e->pos = pos;
268 return(1);
269 } else {
270 return(0);
271 }
272 }
273
274 size_t
275 aura_buffer_tell(struct aura_buffer *e)
276 {
277 return(e->pos);
278 }
279
280 int
281 aura_buffer_eof(struct aura_buffer *e)
282 {
283 return(e->pos >= e->size);
284 }
285
286 char
287 aura_buffer_peek_char(struct aura_buffer *e)
288 {
289 return(e->buf[e->pos]);
290 }
291
292 char
293 aura_buffer_scan_char(struct aura_buffer *e)
294 {
295 return(e->buf[e->pos++]);
296 }
297
298 int
299 aura_buffer_compare(struct aura_buffer *e, char *s)
300 {
301 int i, pos;
302
303 for (i = 0, pos = e->pos; s[i] != '\0' && pos < e->size; i++, pos++) {
304 if (e->buf[pos] != s[i])
305 return(0);
306 }
307
308 if (pos <= e->size) {
309 return(pos);
310 } else {
311 return(0);
312 }
313 }
314
315 int
316 aura_buffer_expect(struct aura_buffer *e, char *s)
317 {
318 int pos;
319
320 if ((pos = aura_buffer_compare(e, s)) > 0) {
321 e->pos = pos;
322 return(1);
323 } else {
324 return(0);
325 }
326 }
327
328 void
329 aura_buffer_push(struct aura_buffer *e, void *src, size_t len)
330 {
331 aura_buffer_ensure_size(e, e->pos + len);
332 memcpy(e->buf + e->pos, src, len);
333 e->pos += len;
334 }
335
336 int
337 aura_buffer_pop(struct aura_buffer *e, void *dest, size_t len)
338 {
339 if (e->pos - len > 0) {
340 e->pos -= len;
341 memcpy(dest, e->buf + e->pos, len);
342 return(1);
343 } else {
344 return(0);
345 }
346 }
0 /*
1 * Copyright (c) 2004 The DragonFly Project. All rights reserved.
2 *
3 * This code is derived from software contributed to The DragonFly Project
4 * by Chris Pressey <cpressey@catseye.mine.nu>.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in
14 * the documentation and/or other materials provided with the
15 * distribution.
16 * 3. Neither the name of The DragonFly Project nor the names of its
17 * contributors may be used to endorse or promote products derived
18 * from this software without specific, prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
26 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
28 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
30 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34 /*
35 * buffer.h
36 * $Id: buffer.h,v 1.1 2004/07/21 19:52:35 cpressey Exp $
37 */
38
39 #ifndef __AURA_BUFFER_H_
40 #define __AURA_BUFFER_H_
41
42 #include <stdlib.h>
43
44 struct aura_buffer {
45 char *buf;
46 size_t len;
47 size_t size;
48 size_t pos;
49 };
50
51 struct aura_buffer *aura_buffer_new(size_t);
52 void aura_buffer_free(struct aura_buffer *);
53 char *aura_buffer_buf(struct aura_buffer *);
54 size_t aura_buffer_len(struct aura_buffer *);
55 size_t aura_buffer_size(struct aura_buffer *);
56
57 void aura_buffer_ensure_size(struct aura_buffer *, size_t);
58 void aura_buffer_set(struct aura_buffer *, char *, size_t);
59 void aura_buffer_append(struct aura_buffer *, char *, size_t);
60
61 void aura_buffer_cpy(struct aura_buffer *, char *);
62 void aura_buffer_cat(struct aura_buffer *, char *);
63 int aura_buffer_cat_file(struct aura_buffer *, char *, ...);
64 int aura_buffer_cat_pipe(struct aura_buffer *, char *, ...);
65
66 int aura_buffer_seek(struct aura_buffer *, size_t);
67 size_t aura_buffer_tell(struct aura_buffer *);
68 int aura_buffer_eof(struct aura_buffer *);
69 char aura_buffer_peek_char(struct aura_buffer *);
70 char aura_buffer_scan_char(struct aura_buffer *);
71 int aura_buffer_compare(struct aura_buffer *, char *);
72 int aura_buffer_expect(struct aura_buffer *, char *);
73
74 void aura_buffer_push(struct aura_buffer *, void *, size_t);
75 int aura_buffer_pop(struct aura_buffer *, void *, size_t);
76
77 #endif /* !__AURA_BUFFER_H_ */
0 #include <stdio.h>
1 #include <stdlib.h>
2
3 #include "builtin.h"
4 #include "value.h"
5 #include "list.h"
6 #include "closure.h"
7
8 #include "symbol.h"
9
10 /*
11 * Built-in operations.
12 * Each of these allocates a new value and returns it,
13 * leaving the passed values untouched.
14 * The single parameter `arg' is always a value of type VALUE_LIST.
15 */
16
17 struct builtin_desc builtins[] = {
18 {"Print", builtin_print},
19 {"Return", builtin_return},
20 {"!", builtin_not},
21 {"&", builtin_and},
22 {"|", builtin_or},
23 {"=", builtin_equ},
24 {"!=", builtin_neq},
25 {">", builtin_gt},
26 {"<", builtin_lt},
27 {">=", builtin_gte},
28 {"<=", builtin_lte},
29 {"+", builtin_add},
30 {"-", builtin_sub},
31 {"*", builtin_mul},
32 {"/", builtin_div},
33 {"%", builtin_mod},
34 {"Index", builtin_index},
35 {NULL, NULL}
36 };
37
38 void
39 builtin_return(struct value **arg)
40 {
41 /* Deref the list. */
42 value_set_from_value(arg, (*arg)->v.l->value);
43 }
44
45 void
46 builtin_print(struct value **arg)
47 {
48 struct list *l;
49 struct value *v;
50
51 for (l = (*arg)->v.l; l != NULL; l = l->next) {
52 v = l->value;
53 switch (v->type) {
54 case VALUE_INTEGER:
55 printf("%d", v->v.i);
56 break;
57 case VALUE_BOOLEAN:
58 printf("%s", v->v.b ? "true" : "false");
59 break;
60 case VALUE_STRING:
61 printf("%s", v->v.s);
62 break;
63 case VALUE_LIST:
64 builtin_print(&v);
65 break;
66 case VALUE_STAB:
67 symbol_table_dump(v->v.stab, 1);
68 break;
69 case VALUE_ERROR:
70 printf("#ERR<%s>", v->v.e);
71 break;
72 case VALUE_BUILTIN:
73 printf("#FN<%08lx>", (unsigned long)v->v.f);
74 break;
75 case VALUE_CLOSURE:
76 closure_dump(v->v.k);
77 break;
78 case VALUE_SYMBOL:
79 symbol_dump(v->v.sym, 0);
80 break;
81 default:
82 printf("???unknown(%d)???", v->type);
83 break;
84 }
85 }
86 }
87
88 /*** logical ***/
89
90 void
91 builtin_not(struct value **arg)
92 {
93 struct value *v;
94
95 v = (*arg)->v.l->value;
96
97 if (v->type == VALUE_BOOLEAN) {
98 value_set_boolean(arg, !v->v.b);
99 } else {
100 value_set_error(arg, "type mismatch");
101 }
102 }
103
104 void
105 builtin_and(struct value **arg)
106 {
107 struct value *l, *r;
108
109 l = (*arg)->v.l->value;
110 r = (*arg)->v.l->next->value;
111
112 if (l->type == VALUE_BOOLEAN && r->type == VALUE_BOOLEAN) {
113 value_set_boolean(arg, l->v.b && r->v.b);
114 } else {
115 value_set_error(arg, "type mismatch");
116 }
117 }
118
119 void
120 builtin_or(struct value **arg)
121 {
122 struct value *l, *r;
123
124 l = (*arg)->v.l->value;
125 r = (*arg)->v.l->next->value;
126
127 if (l->type == VALUE_BOOLEAN && r->type == VALUE_BOOLEAN) {
128 value_set_boolean(arg, l->v.b || r->v.b);
129 } else {
130 value_set_error(arg, "type mismatch");
131 }
132 }
133
134 /*** comparison ***/
135
136 void
137 builtin_equ(struct value **arg)
138 {
139 struct value *l, *r;
140
141 l = (*arg)->v.l->value;
142 r = (*arg)->v.l->next->value;
143
144 if (l->type == VALUE_INTEGER && r->type == VALUE_INTEGER) {
145 value_set_boolean(arg, l->v.i == r->v.i);
146 } else {
147 value_set_error(arg, "type mismatch");
148 }
149 }
150
151 void
152 builtin_neq(struct value **arg)
153 {
154 struct value *l, *r;
155
156 l = (*arg)->v.l->value;
157 r = (*arg)->v.l->next->value;
158
159 if (l->type == VALUE_INTEGER && r->type == VALUE_INTEGER) {
160 value_set_boolean(arg, l->v.i != r->v.i);
161 } else {
162 value_set_error(arg, "type mismatch");
163 }
164 }
165
166 void
167 builtin_gt(struct value **arg)
168 {
169 struct value *l, *r;
170
171 l = (*arg)->v.l->value;
172 r = (*arg)->v.l->next->value;
173
174 if (l->type == VALUE_INTEGER && r->type == VALUE_INTEGER) {
175 value_set_boolean(arg, l->v.i > r->v.i);
176 } else {
177 value_set_error(arg, "type mismatch");
178 }
179 }
180
181 void
182 builtin_lt(struct value **arg)
183 {
184 struct value *l, *r;
185
186 l = (*arg)->v.l->value;
187 r = (*arg)->v.l->next->value;
188
189 if (l->type == VALUE_INTEGER && r->type == VALUE_INTEGER) {
190 value_set_boolean(arg, l->v.i < r->v.i);
191 } else {
192 value_set_error(arg, "type mismatch");
193 }
194 }
195
196 void
197 builtin_gte(struct value **arg)
198 {
199 struct value *l, *r;
200
201 l = (*arg)->v.l->value;
202 r = (*arg)->v.l->next->value;
203
204 if (l->type == VALUE_INTEGER && r->type == VALUE_INTEGER) {
205 value_set_boolean(arg, l->v.i >= r->v.i);
206 } else {
207 value_set_error(arg, "type mismatch");
208 }
209 }
210
211 void
212 builtin_lte(struct value **arg)
213 {
214 struct value *l, *r;
215
216 l = (*arg)->v.l->value;
217 r = (*arg)->v.l->next->value;
218
219 if (l->type == VALUE_INTEGER && r->type == VALUE_INTEGER) {
220 value_set_boolean(arg, l->v.i <= r->v.i);
221 } else {
222 value_set_error(arg, "type mismatch");
223 }
224 }
225
226 /*** arithmetic ***/
227
228 void
229 builtin_add(struct value **arg)
230 {
231 struct value *l, *r;
232
233 l = (*arg)->v.l->value;
234 r = (*arg)->v.l->next->value;
235
236 if (l->type == VALUE_INTEGER && r->type == VALUE_INTEGER) {
237 value_set_integer(arg, l->v.i + r->v.i);
238 } else {
239 value_set_error(arg, "type mismatch");
240 }
241 }
242
243 void
244 builtin_mul(struct value **arg)
245 {
246 struct value *l, *r;
247
248 l = (*arg)->v.l->value;
249 r = (*arg)->v.l->next->value;
250
251 if (l->type == VALUE_INTEGER && r->type == VALUE_INTEGER) {
252 value_set_integer(arg, l->v.i * r->v.i);
253 } else {
254 value_set_error(arg, "type mismatch");
255 }
256 }
257
258 void
259 builtin_sub(struct value **arg)
260 {
261 struct value *l, *r;
262
263 l = (*arg)->v.l->value;
264 r = (*arg)->v.l->next->value;
265
266 if (l->type == VALUE_INTEGER && r->type == VALUE_INTEGER) {
267 value_set_integer(arg, l->v.i - r->v.i);
268 } else {
269 value_set_error(arg, "type mismatch");
270 }
271 }
272
273 void
274 builtin_div(struct value **arg)
275 {
276 struct value *l, *r;
277
278 l = (*arg)->v.l->value;
279 r = (*arg)->v.l->next->value;
280
281 if (l->type == VALUE_INTEGER && r->type == VALUE_INTEGER) {
282 if (r->v.i == 0)
283 value_set_error(arg, "division by zero");
284 else
285 value_set_integer(arg, l->v.i / r->v.i);
286 } else {
287 value_set_error(arg, "type mismatch");
288 }
289 }
290
291 void
292 builtin_mod(struct value **arg)
293 {
294 struct value *l, *r;
295
296 l = (*arg)->v.l->value;
297 r = (*arg)->v.l->next->value;
298
299 if (l->type == VALUE_INTEGER && r->type == VALUE_INTEGER) {
300 if (r->v.i == 0)
301 value_set_error(arg, "modulo by zero");
302 else
303 value_set_integer(arg, l->v.i % r->v.i);
304 } else {
305 value_set_error(arg, "type mismatch");
306 }
307 }
308
309 /*** list ***/
310
311 void
312 builtin_index(struct value **arg)
313 {
314 struct value *l, *r;
315 int count;
316 struct list *li;
317
318 l = (*arg)->v.l->value;
319 r = (*arg)->v.l->next->value;
320
321 if (l->type == VALUE_LIST && r->type == VALUE_INTEGER) {
322 li = l->v.l;
323 for (count = 1; l != NULL && count < r->v.i; count++)
324 li = li->next;
325 if (li == NULL)
326 value_set_error(arg, "no such element");
327 else
328 value_set_from_value(arg, li->value);
329 } else {
330 value_set_error(arg, "type mismatch");
331 }
332 }
0 #ifndef __BUILTIN_H_
1 #define __BUILTIN_H_
2
3 struct value;
4
5 struct builtin_desc {
6 char *name;
7 void (*fn)(struct value **);
8 };
9
10 extern struct builtin_desc builtins[];
11
12 void builtin_print(struct value **);
13
14 void builtin_return(struct value **);
15
16 void builtin_not(struct value **);
17 void builtin_and(struct value **);
18 void builtin_or(struct value **);
19
20 void builtin_equ(struct value **);
21 void builtin_neq(struct value **);
22 void builtin_gt(struct value **);
23 void builtin_lt(struct value **);
24 void builtin_gte(struct value **);
25 void builtin_lte(struct value **);
26
27 void builtin_add(struct value **);
28 void builtin_mul(struct value **);
29 void builtin_sub(struct value **);
30 void builtin_div(struct value **);
31 void builtin_mod(struct value **);
32
33 void builtin_index(struct value **);
34
35 #endif
0 #include <assert.h>
1 #include <stdio.h>
2 #include <stdlib.h>
3
4 #include "mem.h"
5 #include "closure.h"
6 #include "symbol.h"
7 #include "ast.h"
8 #include "activation.h"
9
10 struct closure *
11 closure_new(struct ast *a, struct activation *ar)
12 {
13 struct closure *c;
14
15 assert(a->type == AST_SCOPE);
16
17 c = bhuna_malloc(sizeof(struct closure));
18 c->ast = a;
19 c->ar = ar;
20
21 return(c);
22 }
23
24 void
25 closure_free(struct closure *c)
26 {
27 activation_release(c->ar);
28 bhuna_free(c);
29 }
30
31 void
32 closure_dump(struct closure *c)
33 {
34 #ifdef DEBUG
35 printf("closure{");
36 ast_dump(c->ast, 0);
37 activation_dump(c->ar, 0);
38 printf("}");
39 #endif
40 }
0 #ifndef __CLOSURE_H_
1 #define __CLOSURE_H_
2
3 struct activation;
4 struct ast;
5
6 struct closure {
7 struct ast *ast;
8 struct activation *ar; /* env in which we were created */
9 };
10
11 struct closure *closure_new(struct ast *, struct activation *);
12 void closure_free(struct closure *);
13 void closure_dump(struct closure *);
14
15 #endif
0 /*
1 * Copyright (c) 2004 The DragonFly Project. All rights reserved.
2 *
3 * This code is derived from software contributed to The DragonFly Project
4 * by Chris Pressey <cpressey@catseye.mine.nu>.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in
14 * the documentation and/or other materials provided with the
15 * distribution.
16 * 3. Neither the name of The DragonFly Project nor the names of its
17 * contributors may be used to endorse or promote products derived
18 * from this software without specific, prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
26 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
28 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
30 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34 /*
35 * dict.c
36 * $Id$
37 * Routines to manipulate Bhuna dictionaries.
38 */
39
40 #include <assert.h>
41 #include <stdlib.h>
42 #include <string.h>
43
44 #include "mem.h"
45
46 #include "dict.h"
47 #include "value.h"
48
49 /*** CONSTRUCTOR ***/
50
51 /*
52 * Create a new dictionary.
53 */
54 struct dict *
55 dict_new(void)
56 {
57 struct dict *d;
58 int i;
59
60 d = bhuna_malloc(sizeof(struct dict));
61 d->num_buckets = 31;
62 d->bucket = bhuna_malloc(sizeof(struct chain *) * d->num_buckets);
63 for (i = 0; i < d->num_buckets; i++) {
64 d->bucket[i] = NULL;
65 }
66 d->cursor = NULL;
67 d->cur_bucket = 0;
68
69 return(d);
70 }
71
72 /*** DESTRUCTORS ***/
73
74 static void
75 chain_free(struct chain *c)
76 {
77 assert(c != NULL);
78
79 value_release(c->key);
80 value_release(c->value);
81
82 bhuna_free(c);
83 }
84
85 void
86 dict_free(struct dict *d)
87 {
88 struct chain *c;
89 size_t bucket_no;
90
91 for (bucket_no = 0; bucket_no < d->num_buckets; bucket_no++) {
92 c = d->bucket[bucket_no];
93 while (c != NULL) {
94 d->bucket[bucket_no] = c->next;
95 chain_free(c);
96 c = d->bucket[bucket_no];
97 }
98 }
99 bhuna_free(d);
100 }
101
102 /*** UTILITIES ***/
103
104 /*
105 * Hash function, taken from "Compilers: Principles, Techniques, and Tools"
106 * by Aho, Sethi, & Ullman (a.k.a. "The Dragon Book", 2nd edition.)
107 */
108 static size_t
109 hashpjw(struct value *key, size_t table_size) {
110 char *p;
111 unsigned long int h = 0, g;
112
113 /*
114 * XXX ecks ecks ecks XXX
115 * This is naff... for certain values this will work.
116 * For others, it won't...
117 */
118 for (p = (char *)key; p - (char *)key < sizeof(struct value); p++) {
119 h = (h << 4) + (*p);
120 if ((g = h & 0xf0000000))
121 h = (h ^ (g >> 24)) ^ g;
122 }
123
124 return(h % table_size);
125 }
126
127 /*
128 * Create a new bucket (not called directly by client code.)
129 */
130 static struct chain *
131 chain_new(struct value *key, struct value *value)
132 {
133 struct chain *c;
134
135 c = bhuna_malloc(sizeof(struct chain));
136
137 c->next = NULL;
138 /* XXX grab? */
139 c->key = key;
140 c->value = value;
141
142 return(c);
143 }
144
145 /*
146 * Locate the bucket number a particular key would be located in, and the
147 * chain link itself if such a key exists (or NULL if it could not be found.)
148 */
149 static void
150 dict_locate(struct dict *d, struct value *key,
151 size_t *b_index, struct chain **c)
152 {
153 *b_index = hashpjw(key, d->num_buckets);
154 for (*c = d->bucket[*b_index]; *c != NULL; *c = (*c)->next) {
155 if (value_equal(key, (*c)->key))
156 break;
157 }
158 }
159
160 /*** OPERATIONS ***/
161
162 int dict_exists(struct dict *, struct value *);
163
164 /*
165 * Retrieve a value from a dictionary, given its key.
166 */
167 struct value *
168 dict_fetch(struct dict *d, struct value *k)
169 {
170 struct chain *c;
171 size_t i;
172
173 dict_locate(d, k, &i, &c);
174 if (c != NULL) {
175 /* XXX grab? */
176 return(c->value);
177 } else {
178 return(NULL);
179 }
180 }
181
182 /*
183 * Insert a value into a dictionary.
184 */
185 void
186 dict_store(struct dict *d, struct value *k, struct value *v)
187 {
188 struct chain *c;
189 size_t i;
190
191 dict_locate(d, k, &i, &c);
192 if (c == NULL) {
193 /* Chain does not exist, add a new one. */
194 c = chain_new(k, v);
195 c->next = d->bucket[i];
196 d->bucket[i] = c;
197 } else {
198 /* Chain already exists, replace the value. */
199 value_release(c->value);
200 c->value = v;
201 }
202 }
203
204 int
205 dict_exists(struct dict *d, struct value *key)
206 {
207 struct value *v;
208
209 v = dict_fetch(d, key);
210 return(v != NULL);
211 }
212
213 /*
214 * Finds the next bucket with data in it.
215 * If d->cursor == NULL after this, there is no more data.
216 */
217 static void
218 dict_advance(struct dict *d)
219 {
220 while (d->cursor == NULL) {
221 if (d->cur_bucket == d->num_buckets - 1) {
222 /* We're at eof. Do nothing. */
223 break;
224 } else {
225 d->cur_bucket++;
226 d->cursor = d->bucket[d->cur_bucket];
227 }
228 }
229 }
230
231 void
232 dict_rewind(struct dict *d)
233 {
234 d->cur_bucket = 0;
235 d->cursor = d->bucket[d->cur_bucket];
236 dict_advance(d);
237 }
238
239 int
240 dict_eof(struct dict *d)
241 {
242 return(d->cursor == NULL);
243 }
244
245 struct value *
246 dict_getkey(struct dict *d)
247 {
248 if (d->cursor == NULL) {
249 return(NULL);
250 } else {
251 /* XXX grab? */
252 return(d->cursor->key);
253 }
254 }
255
256 void
257 dict_next(struct dict *d)
258 {
259 if (d->cursor != NULL)
260 d->cursor = d->cursor->next;
261 dict_advance(d);
262 }
263
264 size_t
265 dict_size(struct dict *d)
266 {
267 struct chain *c;
268 int bucket_no;
269 size_t count = 0;
270
271 for (bucket_no = 0; bucket_no < d->num_buckets; bucket_no++) {
272 for (c = d->bucket[bucket_no]; c != NULL; c = c->next)
273 count++;
274 }
275
276 return(count);
277 }
0 /*
1 * Copyright (c) 2004 The DragonFly Project. All rights reserved.
2 *
3 * This code is derived from software contributed to The DragonFly Project
4 * by Chris Pressey <cpressey@catseye.mine.nu>.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in
14 * the documentation and/or other materials provided with the
15 * distribution.
16 * 3. Neither the name of The DragonFly Project nor the names of its
17 * contributors may be used to endorse or promote products derived
18 * from this software without specific, prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
26 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
28 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
30 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34 /*
35 * dict.c
36 * $Id$
37 * Routines to manipulate Bhuna dictionaries.
38 */
39
40 #ifndef __DICT_H_
41 #define __DICT_H_
42
43 struct value;
44
45 struct dict {
46 struct chain **bucket;
47 struct chain *cursor;
48 int cur_bucket;
49 int num_buckets;
50 };
51
52 struct chain {
53 struct chain *next;
54 struct value *key;
55 struct value *value;
56 };
57
58 struct dict *dict_new(void);
59 void dict_free(struct dict *);
60
61 struct value *dict_fetch(struct dict *, struct value *);
62 int dict_exists(struct dict *, struct value *);
63 void dict_store(struct dict *, struct value *, struct value *);
64
65 void dict_rewind(struct dict *);
66 int dict_eof(struct dict *);
67 struct value *dict_getkey(struct dict *);
68 void dict_next(struct dict *);
69
70 size_t dict_size(struct dict *);
71
72 #endif /* !__DICT_H_ */
0 #include <assert.h>
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4
5 #include "ast.h"
6 #include "value.h"
7 #include "symbol.h"
8 #include "list.h"
9 #include "closure.h"
10 #include "activation.h"
11
12 #ifdef DEBUG
13 extern int trace_assignments;
14 extern int trace_calls;
15 extern int trace_ast;
16 extern int trace_closures;
17 #endif
18
19 extern struct activation *current_ar;
20
21 /*** OPERATIONS ***/
22
23 /*
24 * Flatten arguments into a given list value.
25 */
26 static void
27 ast_flatten(struct ast *a, struct value **lvp)
28 {
29 struct value *v = NULL;
30
31 if (a == NULL)
32 return;
33
34 switch (a->type) {
35 case AST_ARG:
36 /*
37 * We go right-to-left here so that our list will
38 * be created the right way 'round.
39 */
40 ast_flatten(a->u.arg.right, lvp);
41 ast_flatten(a->u.arg.left, lvp);
42 break;
43 default:
44 ast_eval(a, &v);
45 value_list_append(lvp, v);
46 value_release(v);
47 }
48 }
49
50 /*** EVALUATOR ***/
51
52 /*
53 * a is roughly analogous to the program counter (PC.)
54 *
55 * v is roughly analogous to the accumulator (A) or top of stack (ToS).
56 */
57 void
58 ast_eval(struct ast *a, struct value **v)
59 {
60 struct symbol *sym;
61 struct value *l = NULL, *r = NULL, *lv = NULL;
62
63 if (a == NULL)
64 return;
65
66 #ifdef DEBUG
67 if (trace_ast) {
68 printf(">>> ENTERING %s[0x%08lx]\n", ast_name(a), (unsigned long)a);
69 }
70 #endif
71
72 switch (a->type) {
73 case AST_SYM:
74 lv = activation_get_value(current_ar, a->u.sym.sym);
75 if (lv == NULL) {
76 printf("*** undefined symbol: ");
77 symbol_dump(a->u.sym.sym, 0);
78 value_set_error(v, "undefined value");
79 } else {
80 value_set_from_value(v, lv);
81 }
82 break;
83 case AST_VALUE:
84 value_set_from_value(v, a->u.value.value);
85 if (*v != NULL && (*v)->type == VALUE_CLOSURE) {
86 /* XXX Freshen the closure. */
87 activation_release((*v)->v.k->ar);
88 activation_grab(current_ar);
89 (*v)->v.k->ar = current_ar;
90 }
91 break;
92 case AST_SCOPE:
93 /*
94 * pretty sure we don't need to do anything with the stab, here.
95 * although we may want to note somewhere that this is the
96 * most recently encountered stab.
97 */
98 ast_eval(a->u.scope.body, v);
99 break;
100 case AST_APPLY:
101 ast_eval(a->u.apply.left, &l);
102 ast_eval(a->u.apply.right, &r);
103 /*
104 * Make the RHS a list (in case it's not) for consistency.
105 */
106 if (r->type == VALUE_LIST) {
107 value_set_from_value(v, r);
108 } else {
109 value_set_list(v);
110 value_list_append(v, r);
111 }
112 value_release(r);
113
114 #ifdef DEBUG
115 if (trace_calls) {
116 printf("---> call:");
117 value_print(l);
118 printf("(");
119 value_print(*v);
120 printf(")\n");
121 }
122 #endif
123
124 /*** BEGIN value_call(l, v); ***/
125
126 if (l->type == VALUE_BUILTIN) {
127 l->v.f(v);
128 } else if (l->type == VALUE_CLOSURE) {
129 struct symbol_table *lstab;
130 struct activation *old_ar;
131
132 assert(l->v.k->ast->type == AST_SCOPE);
133 lstab = l->v.k->ast->u.scope.local;
134
135 /*
136 * Get a new activation record.
137 */
138 old_ar = current_ar;
139
140 /*
141 * Create a new activation record whose lexical
142 * link is the environment of the closure.
143 */
144 current_ar = activation_new(lstab, l->v.k->ar);
145
146 /*
147 * Populate the closure's trapped symbol table with
148 * values taken from the current activation.
149 */
150 /*
151 symbol_table_push_frame(l->v.k->ast->u.scope.trap);
152 */
153
154 /*
155 * Put the arguments into the symbol 'Arg' in the new frame.
156 */
157 sym = symbol_lookup(lstab, "Arg", 0);
158 assert(sym != NULL);
159 activation_set_value(current_ar, sym, *v);
160
161 /*
162 * Evaluate the closure.
163 */
164 ast_eval(l->v.k->ast, v);
165
166 /*
167 * Indicate that we're not longer using ar and that
168 * the refcounter can deallocate it if it wants.
169 */
170 activation_release(current_ar);
171
172 /*
173 * Restore the environment of the symbols to what it was
174 * before the closure was evaluated.
175 */
176 current_ar = old_ar;
177 } else {
178 value_set_error(v, "not executable");
179 }
180
181 /*** END value_call(l, v); ***/
182
183 #ifdef DEBUG
184 if (trace_calls) {
185 printf("<--- call done, retval=");
186 value_print(*v);
187 printf("\n");
188 }
189 #endif
190
191 value_release(l);
192 break;
193 case AST_ARG:
194 value_set_list(v);
195 ast_flatten(a, v);
196 break;
197 case AST_STATEMENT:
198 ast_eval(a->u.statement.left, &l);
199 value_release(l);
200 ast_eval(a->u.statement.right, v);
201 break;
202 case AST_ASSIGNMENT:
203 ast_eval(a->u.assignment.right, v);
204 if (a->u.assignment.left != NULL && a->u.assignment.left->type == AST_SYM) {
205 sym = a->u.assignment.left->u.sym.sym;
206 activation_set_value(current_ar, sym, *v);
207 #ifdef DEBUG
208 if (trace_assignments) {
209 symbol_dump(sym, 1);
210 printf("\n");
211 }
212 #endif
213 } else {
214 value_set_error(v, "bad lvalue");
215 }
216 break;
217 case AST_CONDITIONAL:
218 ast_eval(a->u.conditional.test, &l);
219 if (l == NULL || l->type != VALUE_BOOLEAN) {
220 value_set_error(v, "type mismatch");
221 } else {
222 if (l->v.b) {
223 ast_eval(a->u.conditional.yes, v);
224 } else if (a->u.conditional.no != NULL) {
225 ast_eval(a->u.conditional.no, v);
226 } else {
227 value_set_error(v, "missing else");
228 }
229 }
230 value_release(l);
231 break;
232 case AST_WHILE_LOOP:
233 for (;;) {
234 ast_eval(a->u.while_loop.test, &l);
235 if (l == NULL || l->type != VALUE_BOOLEAN) {
236 value_release(l);
237 value_set_error(v, "type mismatch");
238 break;
239 } else {
240 if (!l->v.b) {
241 /*
242 * `while' condition evaluated to false.
243 */
244 value_release(l);
245 break;
246 }
247 ast_eval(a->u.while_loop.body, v);
248 }
249 }
250 break;
251 }
252
253 #ifdef DEBUG
254 if (trace_ast) {
255 printf("<<< LEAVING %s[0x%08lx] w/value=", ast_name(a), (unsigned long)a);
256 value_print(*v);
257 printf("\n");
258 }
259 #endif
260 }
0 #include <assert.h>
1 #include <stdlib.h>
2 #include <stdio.h>
3
4 #include "mem.h"
5 #include "list.h"
6 #include "value.h"
7
8 void
9 list_cons(struct list **l, struct value *v)
10 {
11 struct list *n;
12
13 n = bhuna_malloc(sizeof(struct list));
14 value_grab(v);
15 n->value = v;
16 n->next = *l;
17 *l = n;
18 }
19
20 void
21 list_free(struct list **l)
22 {
23 struct list *next;
24
25 while ((*l) != NULL) {
26 next = (*l)->next;
27 value_release((*l)->value);
28 bhuna_free((*l));
29 (*l) = next;
30 }
31 }
32
33 size_t
34 list_length(struct list *l)
35 {
36 size_t i = 0;
37
38 while(l != NULL) {
39 i++;
40 l = l->next;
41 }
42
43 return(i);
44 }
45
46 /*
47 * Full comparison used here.
48 */
49 int
50 list_contains(struct list *l, struct value *v)
51 {
52 while (l != NULL) {
53 if (value_equal(l->value, v))
54 return(1);
55 l = l->next;
56 }
57
58 return(0);
59 }
60
61 void
62 list_dump(struct list *l)
63 {
64 printf("[");
65 while (l != NULL) {
66 value_print(l->value);
67 if (l->next != NULL)
68 printf(",");
69 l = l->next;
70 }
71 printf("]");
72 }
0 #ifndef __LIST_H_
1 #define __LIST_H_
2
3 #include <sys/types.h>
4
5 struct value;
6
7 struct list {
8 struct list *next;
9 struct value *value;
10 };
11
12 void list_cons(struct list **, struct value *);
13 void list_free(struct list **);
14 size_t list_length(struct list *);
15 int list_contains(struct list *, struct value *);
16
17 void list_dump(struct list *);
18
19 #endif /* !__LIST_H_ */
0 #include <assert.h>
1 #include <stdio.h>
2 #include <unistd.h>
3
4 #include "scan.h"
5 #include "parse.h"
6 #include "symbol.h"
7 #include "ast.h"
8 #include "builtin.h"
9 #include "value.h"
10 #include "activation.h"
11
12 #ifdef DEBUG
13 int trace_ast = 0;
14 int trace_activations = 0;
15 int trace_calls = 0;
16 int trace_assignments = 0;
17 int trace_refcounting = 0;
18 int trace_closures = 0;
19
20 int num_vars_created = 0;
21 int num_vars_grabbed = 0;
22 int num_vars_released = 0;
23 int num_vars_freed = 0;
24 int num_vars_cowed = 0;
25 int debug_frame = 0;
26 #endif
27
28 struct activation *global_ar;
29 struct activation *current_ar;
30
31 void
32 usage(char **argv)
33 {
34 fprintf(stderr, "Usage: %s "
35 #ifdef DEBUG
36 "[-acfknprstvz] "
37 #endif
38 "source\n",
39 argv[0]);
40 #ifdef DEBUG
41 fprintf(stderr, " -a: trace assignments\n");
42 fprintf(stderr, " -c: trace calls\n");
43 fprintf(stderr, " -f: trace frames\n");
44 fprintf(stderr, " -k: trace closures\n");
45 fprintf(stderr, " -n: don't actually run program\n");
46 fprintf(stderr, " -p: dump program AST before run\n");
47 fprintf(stderr, " -r: show reference counting stats (-rr = trace refcounting)\n");
48 fprintf(stderr, " -s: dump symbol table before run\n");
49 fprintf(stderr, " -t: trace AST transitions in evaluator\n");
50 fprintf(stderr, " -v: trace activation records\n");
51 fprintf(stderr, " -z: dump symbol table after run\n");
52 #endif
53 exit(1);
54 }
55
56 void
57 load_builtins(struct symbol_table *stab, struct builtin_desc *b)
58 {
59 int i;
60 struct value *v;
61 struct symbol *sym;
62
63 for (i = 0; b[i].name != NULL; i++) {
64 sym = symbol_define(stab, b[i].name, SYM_KIND_COMMAND);
65 v = value_new_builtin(b[i].fn);
66 activation_set_value(global_ar, sym, v);
67 value_release(v);
68 }
69
70 /* XXX */
71 sym = symbol_define(stab, "EoL", SYM_KIND_VARIABLE);
72 v = value_new_string("\n");
73 activation_set_value(global_ar, sym, v);
74 value_release(v);
75
76 sym = symbol_define(stab, "True", SYM_KIND_VARIABLE);
77 v = value_new_boolean(1);
78 activation_set_value(global_ar, sym, v);
79 value_release(v);
80
81 sym = symbol_define(stab, "False", SYM_KIND_VARIABLE);
82 v = value_new_boolean(0);
83 activation_set_value(global_ar, sym, v);
84 value_release(v);
85 }
86
87 int
88 main(int argc, char **argv)
89 {
90 char **real_argv = argv;
91 struct scan_st *sc;
92 struct symbol_table *stab;
93 struct ast *a;
94 struct value *v;
95 char *source = NULL;
96 int opt;
97 #ifdef DEBUG
98 int run_program = 1;
99 int dump_symbols_beforehand = 0;
100 int dump_symbols_afterwards = 0;
101 int dump_program = 0;
102 #define OPTS "acfknprstvz"
103 #define RUN_PROGRAM run_program
104 #else
105 #define OPTS ""
106 #define RUN_PROGRAM 1
107 #endif
108
109 #ifdef DEBUG
110 setvbuf(stdout, NULL, _IOLBF, 0);
111 #endif
112
113 /*
114 * Get command-line arguments.
115 */
116 while ((opt = getopt(argc, argv, OPTS)) != -1) {
117 switch(opt) {
118 #ifdef DEBUG
119 case 'a':
120 trace_assignments++;
121 break;
122 case 'c':
123 trace_calls++;
124 break;
125 case 'f':
126 debug_frame++;
127 break;
128 case 'k':
129 trace_closures++;
130 break;
131 case 'n':
132 run_program = 0;
133 break;
134 case 'p':
135 dump_program = 1;
136 break;
137 case 'r':
138 trace_refcounting++;
139 break;
140 case 's':
141 dump_symbols_beforehand = 1;
142 break;
143 case 't':
144 trace_ast++;
145 break;
146 case 'v':
147 trace_activations++;
148 break;
149 case 'z':
150 dump_symbols_afterwards = 1;
151 break;
152 #endif
153 case '?':
154 default:
155 usage(argv);
156 }
157 }
158 argc -= optind;
159 argv += optind;
160
161 if (*argv != NULL)
162 source = *argv;
163 else
164 usage(real_argv);
165
166 if ((sc = scan_open(source)) != NULL) {
167 stab = symbol_table_new(NULL);
168 global_ar = activation_new(stab, NULL);
169 load_builtins(stab, builtins);
170 a = parse_program(sc, stab);
171 scan_close(sc);
172 #ifdef DEBUG
173 if (dump_symbols_beforehand)
174 symbol_table_dump(stab, 1);
175 if (dump_program) {
176 ast_dump(a, 0);
177 }
178 #endif
179 if (sc->errors == 0 && RUN_PROGRAM) {
180 v = value_new_integer(76);
181 current_ar = global_ar;
182 ast_eval(a, &v);
183 value_release(v);
184 }
185 #ifdef DEBUG
186 if (dump_symbols_afterwards)
187 symbol_table_dump(stab, 1);
188 #endif
189 ast_free(a);
190 symbol_table_free(stab);
191 #ifdef DEBUG
192 if (trace_refcounting > 0) {
193 value_dump_global_table();
194 printf("Created: %8d\n", num_vars_created);
195 printf("Grabbed: %8d\n", num_vars_grabbed);
196 printf("Released: %8d\n", num_vars_released);
197 printf("Freed: %8d\n", num_vars_freed);
198 printf("CoW'ed: %8d\n", num_vars_cowed);
199 }
200 #endif
201 return(0);
202 } else {
203 fprintf(stderr, "Can't open `%s'\n", source);
204 return(1);
205 }
206 }
0 /*
1 * Copyright (c) 2004 The DragonFly Project. All rights reserved.
2 *
3 * This code is derived from software contributed to The DragonFly Project
4 * by Chris Pressey <cpressey@catseye.mine.nu>.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in
14 * the documentation and/or other materials provided with the
15 * distribution.
16 * 3. Neither the name of The DragonFly Project nor the names of its
17 * contributors may be used to endorse or promote products derived
18 * from this software without specific, prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
26 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
28 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
30 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34 /*
35 * mem.c
36 * $Id$
37 * Bhuna memory management functions.
38 */
39
40 #include <assert.h>
41 #include <stdlib.h>
42 #include <string.h>
43
44 void *
45 bhuna_malloc(size_t size, char *what)
46 {
47 void *ptr;
48
49 ptr = malloc(size);
50 assert(ptr != NULL);
51 bzero(ptr, size);
52
53 return(ptr);
54 }
55
56 char *
57 bhuna_strdup(char *string)
58 {
59 char *ptr;
60
61 ptr = strdup(string);
62 assert(ptr != NULL);
63
64 return(ptr);
65 }
66
67 void
68 bhuna_free(void *ptr)
69 {
70 assert(ptr != NULL);
71 free(ptr);
72 }
0 /*
1 * Copyright (c) 2004 The DragonFly Project. All rights reserved.
2 *
3 * This code is derived from software contributed to The DragonFly Project
4 * by Chris Pressey <cpressey@catseye.mine.nu>.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in
14 * the documentation and/or other materials provided with the
15 * distribution.
16 * 3. Neither the name of The DragonFly Project nor the names of its
17 * contributors may be used to endorse or promote products derived
18 * from this software without specific, prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
26 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
28 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
30 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34 /*
35 * mem.h
36 * $Id$
37 * Bhuna memory management functions and macros.
38 */
39
40 #ifndef __MEM_H_
41 #define __MEM_H_
42
43 #include <sys/types.h>
44
45 #ifdef DEBUG
46 void *bhuna_malloc(size_t);
47 char *bhuna_strdup(char *);
48 void bhuna_free(void *);
49 #else
50 #define bhuna_malloc(x) malloc(x)
51 #define bhuna_strdup(x) strdup(x)
52 #define bhuna_free(x) free(x)
53 #endif
54
55 #endif
0 /*
1 * Copyright (c)2004 Cat's Eye Technologies. All rights reserved.
2 *
3 * Redistribution and use in source and binary forms, with or without
4 * modification, are permitted provided that the following conditions
5 * are met:
6 *
7 * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 *
10 * Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in
12 * the documentation and/or other materials provided with the
13 * distribution.
14 *
15 * Neither the name of Cat's Eye Technologies nor the names of its
16 * contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
24 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
25 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
28 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
30 * OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32 /*
33 * parse.c
34 * Recursive-descent parser for Bhuna.
35 * $Id: parse.c 54 2004-04-23 22:51:09Z catseye $
36 */
37
38 #include <assert.h>
39 #include <ctype.h>
40 #include <stdio.h>
41 #include <stdlib.h>
42 #include <string.h>
43
44 #include "scan.h"
45 #include "parse.h"
46 #include "symbol.h"
47 #include "value.h"
48 #include "atom.h"
49 #include "ast.h"
50
51 #define VAR_LOCAL 0
52 #define VAR_GLOBAL 1
53
54 #define VAR_MUST_EXIST 0
55 #define VAR_MAY_EXIST 1
56 #define VAR_MUST_NOT_EXIST 2
57
58 /* util */
59
60 struct ast *
61 ast_new_empty_list(struct symbol_table *stab)
62 {
63 struct value *v;
64 struct ast *a;
65
66 /*
67 * Optimization: make this one symbol once,
68 * share it as a global value...
69 */
70 v = value_new_list();
71 a = ast_new_value(v);
72 value_release(v);
73 return(a);
74 }
75
76 /* ---------------- TOP LEVEL ----------------*/
77
78 struct ast *
79 parse_program(struct scan_st *sc, struct symbol_table *stab)
80 {
81 struct ast *a = NULL;
82
83 while (sc->type != TOKEN_EOF) {
84 a = ast_new_statement(a, parse_statement(sc, stab));
85 }
86
87 return(a);
88 }
89
90 /*
91 * Caller must allocate *istab if they want us to have one.
92 * Otherwise they should set it to NULL, and we'll just use the one above.
93 */
94 struct ast *
95 parse_block(struct scan_st *sc, struct symbol_table *stab,
96 struct symbol_table **istab)
97 {
98 struct ast *a = NULL;
99 /* struct value *v;
100 struct symbol *sym; */
101
102 assert(*istab != NULL);
103
104 if (tokeq(sc, "{")) {
105 scan_expect(sc, "{");
106 while (tokne(sc, "}") && sc->type != TOKEN_EOF) {
107 a = ast_new_statement(a, parse_statement(sc, *istab));
108 }
109 scan_expect(sc, "}");
110 } else {
111 a = parse_statement(sc, *istab);
112 }
113
114 /*
115 * For housekeeping, we place a reference to this symbol table
116 * in an anonymous symbol in the overlying symbol table.
117 */
118 /*
119 if (!symbol_table_is_empty(*istab) != NULL) {
120 sym = symbol_define(stab, NULL, SYM_KIND_ANONYMOUS);
121 v = value_new_symbol_table(*istab);
122 symbol_set_value(sym, v);
123 value_release(v);
124 }
125 */
126
127 return(a);
128 }
129
130 struct ast *
131 parse_statement(struct scan_st *sc, struct symbol_table *stab)
132 {
133 struct symbol_table *istab;
134 struct ast *a, *l, *r;
135
136 if (tokeq(sc, "{")) {
137 istab = symbol_table_new(stab);
138 a = parse_block(sc, stab, &istab);
139 } else if (tokeq(sc, "if")) {
140 scan(sc);
141 a = parse_expr(sc, stab, 0);
142 istab = symbol_table_new(stab);
143 l = parse_block(sc, stab, &istab);
144 if (tokeq(sc, "else")) {
145 scan(sc);
146 istab = symbol_table_new(stab);
147 r = parse_block(sc, stab, &istab);
148 } else {
149 r = NULL;
150 }
151 a = ast_new_conditional(a, l, r);
152 } else if (tokeq(sc, "while")) {
153 scan(sc);
154 l = parse_expr(sc, stab, 0);
155 istab = symbol_table_new(stab);
156 r = parse_block(sc, stab, &istab);
157 a = ast_new_while_loop(l, r);
158 } else if (tokeq(sc, "local")) {
159 scan(sc);
160 a = parse_assignment(sc, stab);
161 } else {
162 if (symbol_lookup(stab, sc->token, VAR_GLOBAL) == NULL) {
163 /*
164 * Symbol doesn't exist at all - it MUST be
165 * an assignment, and it MUST be local.
166 */
167 a = parse_assignment(sc, stab);
168 } else {
169 a = parse_command(sc, stab);
170 }
171 }
172 if (tokeq(sc, ";"))
173 scan(sc);
174 return(a);
175 }
176
177 struct ast *
178 parse_assignment(struct scan_st *sc, struct symbol_table *stab)
179 {
180 struct symbol *sym;
181 struct ast *l, *r;
182
183 l = parse_var(sc, stab, &sym, VAR_LOCAL, VAR_MUST_NOT_EXIST);
184 scan_expect(sc, "=");
185 r = parse_expr(sc, stab, 0);
186 return(ast_new_assignment(l, r));
187 }
188
189 struct ast *
190 parse_command(struct scan_st *sc, struct symbol_table *stab)
191 {
192 struct symbol *sym;
193 struct ast *a, *l, *r;
194
195 a = parse_var(sc, stab, &sym, VAR_GLOBAL, VAR_MUST_EXIST);
196 if (tokeq(sc, "=")) {
197 /*
198 * Actually... it's an assignment to an already-existing variable.
199 */
200 scan(sc);
201 r = parse_expr(sc, stab, 0);
202 a = ast_new_assignment(a, r);
203 return(a);
204 }
205
206 if (tokne(sc, "}") && tokne(sc, ";") && sc->type != TOKEN_EOF) {
207 l = parse_expr(sc, stab, 0);
208 while (tokeq(sc, ",")) {
209 scan_expect(sc, ",");
210 r = parse_expr(sc, stab, 0);
211 l = ast_new_arg(l, r);
212 }
213 } else {
214 l = ast_new_empty_list(stab);
215 }
216 a = ast_new_apply(a, l);
217
218 return(a);
219 }
220
221 /* ------------------------- EXPRESSIONS ------------------------ */
222
223 int maxlevel = 3;
224
225 char *op[4][6] = {
226 { "&", "|", "", "", "", "" },
227 { "=", "!=", ">", "<", ">=", "<=" },
228 { "+", "-", "", "", "", "" },
229 { "*", "/", "%", "", "", "" }
230 };
231
232 struct ast *
233 parse_expr(struct scan_st *sc, struct symbol_table *stab, int level)