1 ////////////////////////////////////////////////////////////////////////////////
5 // Copyright 2011 Zach Wegner
7 // Licensed under the Apache License, Version 2.0 (the "License");
8 // you may not use this file except in compliance with the License.
9 // You may obtain a copy of the License at
11 // http://www.apache.org/licenses/LICENSE-2.0
13 // Unless required by applicable law or agreed to in writing, software
14 // distributed under the License is distributed on an "AS IS" BASIS,
15 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 // See the License for the specific language governing permissions and
17 // limitations under the License.
19 ////////////////////////////////////////////////////////////////////////////////
21 #define __STDC_FORMAT_MACROS
37 __attribute((noreturn
)) void error(const char *msg
, ...) {
53 typedef int64_t int_t
;
55 typedef std::pair
<node
*, node
*> node_pair
;
56 typedef std::map
<const char *, node
*> symbol_table
;
57 typedef std::map
<int_t
, node_pair
> node_dict
;
58 typedef std::map
<int_t
, node
*> node_set
;
59 typedef std::vector
<node
*> node_list
;
61 node
*builtin_dict(context
*globals
, context
*ctx
, list
*args
, dict
*kwargs
);
62 node
*builtin_dict_get(context
*globals
, context
*ctx
, list
*args
, dict
*kwargs
);
63 node
*builtin_dict_keys(context
*globals
, context
*ctx
, list
*args
, dict
*kwargs
);
64 node
*builtin_fread(context
*globals
, context
*ctx
, list
*args
, dict
*kwargs
);
65 node
*builtin_isinstance(context
*globals
, context
*ctx
, list
*args
, dict
*kwargs
);
66 node
*builtin_len(context
*globals
, context
*ctx
, list
*args
, dict
*kwargs
);
67 node
*builtin_list(context
*globals
, context
*ctx
, list
*args
, dict
*kwargs
);
68 node
*builtin_list_append(context
*globals
, context
*ctx
, list
*args
, dict
*kwargs
);
69 node
*builtin_list_index(context
*globals
, context
*ctx
, list
*args
, dict
*kwargs
);
70 node
*builtin_list_pop(context
*globals
, context
*ctx
, list
*args
, dict
*kwargs
);
71 node
*builtin_open(context
*globals
, context
*ctx
, list
*args
, dict
*kwargs
);
72 node
*builtin_ord(context
*globals
, context
*ctx
, list
*args
, dict
*kwargs
);
73 node
*builtin_print(context
*globals
, context
*ctx
, list
*args
, dict
*kwargs
);
74 node
*builtin_print_nonl(context
*globals
, context
*ctx
, list
*args
, dict
*kwargs
);
75 node
*builtin_range(context
*globals
, context
*ctx
, list
*args
, dict
*kwargs
);
76 node
*builtin_reversed(context
*globals
, context
*ctx
, list
*args
, dict
*kwargs
);
77 node
*builtin_set(context
*globals
, context
*ctx
, list
*args
, dict
*kwargs
);
78 node
*builtin_set_add(context
*globals
, context
*ctx
, list
*args
, dict
*kwargs
);
79 node
*builtin_sorted(context
*globals
, context
*ctx
, list
*args
, dict
*kwargs
);
80 node
*builtin_str_join(context
*globals
, context
*ctx
, list
*args
, dict
*kwargs
);
81 node
*builtin_str_upper(context
*globals
, context
*ctx
, list
*args
, dict
*kwargs
);
82 node
*builtin_str_startswith(context
*globals
, context
*ctx
, list
*args
, dict
*kwargs
);
83 node
*builtin_zip(context
*globals
, context
*ctx
, list
*args
, dict
*kwargs
);
85 inline node
*create_bool_const(bool b
);
91 virtual const char *node_type() { return "node"; }
93 virtual void mark_live() { error("mark_live unimplemented for %s", this->node_type()); }
94 #define MARK_LIVE_FN \
95 virtual void mark_live() { allocator->mark_live(this, sizeof(*this)); }
96 #define MARK_LIVE_SINGLETON_FN virtual void mark_live() { }
98 virtual bool is_bool() { return false; }
99 virtual bool is_dict() { return false; }
100 virtual bool is_file() { return false; }
101 virtual bool is_function() { return false; }
102 virtual bool is_int_const() { return false; }
103 virtual bool is_list() { return false; }
104 virtual bool is_none() { return false; }
105 virtual bool is_set() { return false; }
106 virtual bool is_string() { return false; }
107 virtual bool bool_value() { error("bool_value unimplemented for %s", this->node_type()); return false; }
108 virtual int_t
int_value() { error("int_value unimplemented for %s", this->node_type()); return 0; }
109 virtual std::string
string_value() { error("string_value unimplemented for %s", this->node_type()); return NULL
; }
110 virtual node_list
*list_value() { error("list_value unimplemented for %s", this->node_type()); return NULL
; }
112 #define UNIMP_OP(NAME) \
113 virtual node *__##NAME##__(node *rhs) { error(#NAME " unimplemented for %s", this->node_type()); return NULL; }
129 #define UNIMP_CMP_OP(NAME) \
130 virtual bool _##NAME(node *rhs) { error(#NAME " unimplemented for %s", this->node_type()); return false; } \
131 node *__##NAME##__(node *rhs) { return create_bool_const(this->_##NAME(rhs)); }
142 #define UNIMP_UNOP(NAME) \
143 virtual node *__##NAME##__() { error(#NAME " unimplemented for %s", this->node_type()); return NULL; }
151 node
*__getattr__(node
*rhs
);
153 node
*__is__(node
*rhs
);
154 node
*__isnot__(node
*rhs
);
158 virtual node
*__ncontains__(node
*rhs
) { return this->__contains__(rhs
)->__not__(); }
160 virtual node
*__call__(context
*globals
, context
*ctx
, list
*args
, dict
*kwargs
) { error("call unimplemented for %s", this->node_type()); return NULL
; }
161 virtual void __delitem__(node
*rhs
) { error("delitem unimplemented for %s", this->node_type()); }
162 virtual node
*__getitem__(node
*rhs
) { error("getitem unimplemented for %s", this->node_type()); return NULL
; }
163 virtual node
*__getitem__(int index
) { error("getitem unimplemented for %s", this->node_type()); return NULL
; }
164 virtual void __setattr__(node
*rhs
, node
*key
) { error("setattr unimplemented for %s", this->node_type()); }
165 virtual void __setitem__(node
*key
, node
*value
) { error("setitem unimplemented for %s", this->node_type()); }
166 virtual node
*__slice__(node
*start
, node
*end
, node
*step
) { error("slice unimplemented for %s", this->node_type()); return NULL
; }
168 // unwrapped versions
169 virtual int_t
len() { error("len unimplemented for %s", this->node_type()); return 0; }
170 virtual node
*getattr(const char *rhs
) { error("getattr unimplemented (%s) for %s", rhs
, this->node_type()); return NULL
; }
171 virtual int_t
hash() { error("hash unimplemented for %s", this->node_type()); return 0; }
172 virtual std::string
repr() { error("repr unimplemented for %s", this->node_type()); return NULL
; }
173 virtual std::string
str() { return repr(); }
178 symbol_table symbols
;
183 this->parent_ctx
= NULL
;
185 context(context
*parent_ctx
) {
186 this->parent_ctx
= parent_ctx
;
189 void mark_live(bool free_ctx
) {
191 for (symbol_table::const_iterator i
= this->symbols
.begin(); i
!= this->symbols
.end(); i
++)
192 i
->second
->mark_live();
193 if (this->parent_ctx
)
194 this->parent_ctx
->mark_live(false);
197 void store(const char *name
, node
*obj
) {
198 this->symbols
[name
] = obj
;
200 node
*load(const char *name
) {
201 symbol_table::const_iterator v
= this->symbols
.find(name
);
202 if (v
== this->symbols
.end())
203 error("cannot find '%s' in symbol table", name
);
207 for (symbol_table::const_iterator i
= this->symbols
.begin(); i
!= this->symbols
.end(); i
++)
208 if (i
->second
->is_int_const())
209 printf("symbol['%s'] = int(%" PRId64
");\n", i
->first
, i
->second
->int_value());
211 printf("symbol['%s'] = %p;\n", i
->first
, i
->second
);
215 class none_const
: public node
{
217 // For some reason this causes errors without an argument to the constructor...
218 none_const(int_t value
) { }
219 const char *node_type() { return "none"; }
221 MARK_LIVE_SINGLETON_FN
223 virtual bool is_none() { return true; }
224 virtual bool bool_value() { return false; }
226 virtual bool _eq(node
*rhs
);
227 virtual int_t
hash() { return 0; }
228 virtual std::string
repr() { return std::string("None"); }
231 class int_const
: public node
{
236 int_const(int_t value
) {
239 const char *node_type() { return "int"; }
243 virtual bool is_int_const() { return true; }
244 virtual int_t
int_value() { return this->value
; }
245 virtual bool bool_value() { return this->value
!= 0; }
247 #define INT_OP(NAME, OP) \
248 virtual int_t _##NAME(node *rhs) { \
249 return this->int_value() OP rhs->int_value(); \
251 virtual node *__##NAME##__(node *rhs) { \
252 return new(allocator) int_const(this->_##NAME(rhs)); \
265 #define CMP_OP(NAME, OP) \
266 virtual bool _##NAME(node *rhs) { \
267 return this->int_value() OP rhs->int_value(); \
277 #define INT_UNOP(NAME, OP) \
278 virtual node *__##NAME##__() { \
279 return new(allocator) int_const(OP this->int_value()); \
285 virtual int_t
hash() { return this->value
; }
286 virtual node
*getattr(const char *key
);
287 virtual std::string
repr();
290 class int_const_singleton
: public int_const
{
292 int_const_singleton(int_t value
) : int_const(value
) { }
294 MARK_LIVE_SINGLETON_FN
297 class bool_const
: public node
{
302 bool_const(bool value
) {
305 const char *node_type() { return "bool"; }
307 MARK_LIVE_SINGLETON_FN
309 virtual bool is_bool() { return true; }
310 virtual bool bool_value() { return this->value
; }
311 virtual int_t
int_value() { return (int_t
)this->value
; }
313 #define BOOL_AS_INT_OP(NAME, OP) \
314 virtual node *__##NAME##__(node *rhs) { \
315 if (rhs->is_int_const() || rhs->is_bool()) \
316 return new(allocator) int_const(this->int_value() OP rhs->int_value()); \
317 error(#NAME " error in bool"); \
320 BOOL_AS_INT_OP(add
, +)
321 BOOL_AS_INT_OP(floordiv
, /)
322 BOOL_AS_INT_OP(lshift
, <<)
323 BOOL_AS_INT_OP(mod
, %)
324 BOOL_AS_INT_OP(mul
, *)
325 BOOL_AS_INT_OP(rshift
, >>)
326 BOOL_AS_INT_OP(sub
, -)
328 #define BOOL_INT_CHECK_OP(NAME, OP) \
329 virtual node *__##NAME##__(node *rhs) { \
330 if (rhs->is_bool()) \
331 return new(allocator) bool_const((bool)(this->int_value() OP rhs->int_value())); \
332 else if (rhs->is_int_const()) \
333 return new(allocator) int_const(this->int_value() OP rhs->int_value()); \
334 error(#NAME " error in bool"); \
338 BOOL_INT_CHECK_OP(and, &)
339 BOOL_INT_CHECK_OP(or, |)
340 BOOL_INT_CHECK_OP(xor, ^)
342 #define BOOL_OP(NAME, OP) \
343 virtual bool _##NAME(node *rhs) { \
344 if (rhs->is_int_const() || rhs->is_bool()) \
345 return this->int_value() OP rhs->int_value(); \
346 error(#NAME " error in bool"); \
356 virtual int_t
hash() { return (int_t
)this->value
; }
357 virtual std::string
repr();
360 class string_const
: public node
{
365 string_const(std::string value
) {
368 const char *node_type() { return "str"; }
372 virtual bool is_string() { return true; }
373 virtual std::string
string_value() { return this->value
; }
374 virtual bool bool_value() { return this->len() != 0; }
376 std::string::iterator
begin() { return value
.begin(); }
377 std::string::iterator
end() { return value
.end(); }
379 #define STRING_OP(NAME, OP) \
380 virtual bool _##NAME(node *rhs) { \
381 if (rhs->is_string()) \
382 return this->string_value() OP rhs->string_value(); \
383 error(#NAME " unimplemented"); \
394 virtual node
*__mod__(node
*rhs
);
395 virtual node
*__add__(node
*rhs
);
396 virtual node
*__mul__(node
*rhs
);
398 virtual node
*getattr(const char *key
);
400 virtual node
*__getitem__(node
*rhs
) {
401 if (!rhs
->is_int_const()) {
402 error("getitem unimplemented");
405 return new(allocator
) string_const(value
.substr(rhs
->int_value(), 1));
408 virtual int_t
hash() {
409 int_t hashkey
= 14695981039346656037ull;
410 for (std::string::iterator c
= this->begin(); c
!= this->end(); c
++) {
412 hashkey
*= 1099511628211ll;
416 virtual int_t
len() {
417 return value
.length();
419 virtual node
*__slice__(node
*start
, node
*end
, node
*step
) {
420 if ((!start
->is_none() && !start
->is_int_const()) ||
421 (!end
->is_none() && !end
->is_int_const()) ||
422 (!step
->is_none() && !step
->is_int_const()))
423 error("slice error");
424 int_t lo
= start
->is_none() ? 0 : start
->int_value();
425 int_t hi
= end
->is_none() ? value
.length() : end
->int_value();
426 int_t st
= step
->is_none() ? 1 : step
->int_value();
428 error("slice step != 1 not supported for string");
429 return new(allocator
) string_const(this->value
.substr(lo
, hi
- lo
+ 1));
431 virtual std::string
repr() {
433 s
+= this->value
; // XXX Add proper quoting/escaping
437 virtual std::string
str() { return this->value
; }
440 class string_const_singleton
: public string_const
{
445 string_const_singleton(std::string value
, int_t hashkey
) : string_const(value
), hashkey(hashkey
) { }
447 MARK_LIVE_SINGLETON_FN
449 virtual int_t
hash() {
450 return this->hashkey
;
454 class list
: public node
{
460 list(node_list
&l
) : items(l
) { }
461 const char *node_type() { return "list"; }
463 virtual void mark_live() {
464 if (!allocator
->mark_live(this, sizeof(*this))) {
465 for (size_t i
= 0; i
< this->items
.size(); i
++)
466 this->items
[i
]->mark_live();
470 void append(node
*obj
) {
471 items
.push_back(obj
);
473 void prepend(node
*obj
) {
474 items
.insert(items
.begin(), obj
);
477 // would be nice if STL wasn't stupid, and this was one line...
478 node
*popped
= items
.back();
482 node_list::iterator
begin() { return items
.begin(); }
483 node_list::iterator
end() { return items
.end(); }
484 int_t
index(int_t base
) {
486 base
= items
.size() + base
;
490 virtual bool is_list() { return true; }
491 virtual node_list
*list_value() { return &items
; }
492 virtual bool bool_value() { return this->len() != 0; }
494 virtual node
*__add__(node
*rhs
);
495 virtual node
*__mul__(node
*rhs
);
497 virtual node
*__contains__(node
*key
) {
499 for (size_t i
= 0; i
< this->items
.size(); i
++)
500 if (this->items
[i
]->_eq(key
)) {
504 return create_bool_const(found
);
506 virtual void __delitem__(node
*rhs
) {
507 if (!rhs
->is_int_const()) {
508 error("delitem unimplemented");
511 node_list::iterator f
= items
.begin() + this->index(rhs
->int_value());
514 virtual node
*__getitem__(int idx
) {
515 return this->items
[this->index(idx
)];
517 virtual node
*__getitem__(node
*rhs
) {
518 if (!rhs
->is_int_const()) {
519 error("getitem unimplemented");
522 return this->__getitem__(rhs
->int_value());
524 virtual int_t
len() {
525 return this->items
.size();
527 virtual void __setitem__(node
*key
, node
*value
) {
528 if (!key
->is_int_const())
529 error("error in list.setitem");
530 int_t idx
= key
->int_value();
531 items
[this->index(idx
)] = value
;
533 virtual node
*__slice__(node
*start
, node
*end
, node
*step
) {
534 if ((!start
->is_none() && !start
->is_int_const()) ||
535 (!end
->is_none() && !end
->is_int_const()) ||
536 (!step
->is_none() && !step
->is_int_const()))
537 error("slice error");
538 int_t lo
= start
->is_none() ? 0 : start
->int_value();
539 int_t hi
= end
->is_none() ? items
.size() : end
->int_value();
540 int_t st
= step
->is_none() ? 1 : step
->int_value();
541 list
*new_list
= new(allocator
) list();
542 for (; st
> 0 ? (lo
< hi
) : (lo
> hi
); lo
+= st
)
543 new_list
->append(items
[lo
]);
546 virtual std::string
repr() {
547 std::string new_string
= "[";
549 for (node_list::iterator i
= this->items
.begin(); i
!= this->items
.end(); i
++) {
553 new_string
+= (*i
)->repr();
558 virtual node
*getattr(const char *key
);
561 class dict
: public node
{
567 const char *node_type() { return "dict"; }
569 virtual void mark_live() {
570 if (!allocator
->mark_live(this, sizeof(*this))) {
571 for (node_dict::iterator i
= this->items
.begin(); i
!= this->items
.end(); i
++) {
572 i
->second
.first
->mark_live();
573 i
->second
.second
->mark_live();
578 node
*lookup(node
*key
) {
580 if (key
->is_int_const())
581 hashkey
= key
->int_value();
583 hashkey
= key
->hash();
584 node_dict::const_iterator v
= this->items
.find(hashkey
);
585 if (v
== this->items
.end())
587 node
*k
= v
->second
.first
;
590 return v
->second
.second
;
592 node_dict::iterator
begin() { return items
.begin(); }
593 node_dict::iterator
end() { return items
.end(); }
595 virtual bool is_dict() { return true; }
596 virtual bool bool_value() { return this->len() != 0; }
598 virtual node
*__contains__(node
*key
) {
599 return create_bool_const(this->lookup(key
) != NULL
);
601 virtual node
*__getitem__(node
*key
) {
602 node
*value
= this->lookup(key
);
604 error("cannot find %s in dict", key
->repr().c_str());
607 virtual int_t
len() {
608 return this->items
.size();
610 virtual void __setitem__(node
*key
, node
*value
) {
612 if (key
->is_int_const())
613 hashkey
= key
->int_value();
615 hashkey
= key
->hash();
616 items
[hashkey
] = node_pair(key
, value
);
618 virtual std::string
repr() {
619 std::string new_string
= "{";
621 for (node_dict::iterator i
= this->items
.begin(); i
!= this->items
.end(); i
++) {
625 new_string
+= i
->second
.first
->repr() + ": " + i
->second
.second
->repr();
630 virtual node
*getattr(const char *key
);
633 class set
: public node
{
639 const char *node_type() { return "set"; }
641 virtual void mark_live() {
642 if (!allocator
->mark_live(this, sizeof(*this))) {
643 for (node_set::iterator i
= this->items
.begin(); i
!= this->items
.end(); i
++)
644 i
->second
->mark_live();
648 node
*lookup(node
*key
) {
650 if (key
->is_int_const())
651 hashkey
= key
->int_value();
653 hashkey
= key
->hash();
654 node_set::const_iterator v
= this->items
.find(hashkey
);
655 if (v
== this->items
.end() || !v
->second
->_eq(key
))
659 void add(node
*key
) {
661 if (key
->is_int_const())
662 hashkey
= key
->int_value();
664 hashkey
= key
->hash();
665 items
[hashkey
] = key
;
668 virtual bool is_set() { return true; }
669 virtual bool bool_value() { return this->len() != 0; }
671 virtual node
*__contains__(node
*key
) {
672 return create_bool_const(this->lookup(key
) != NULL
);
674 virtual int_t
len() {
675 return this->items
.size();
677 virtual std::string
repr() {
678 if (!this->items
.size())
680 std::string new_string
= "{";
682 for (node_set::iterator i
= this->items
.begin(); i
!= this->items
.end(); i
++) {
686 new_string
+= i
->second
->repr();
691 virtual node
*getattr(const char *key
);
694 class object
: public node
{
700 this->items
= new(allocator
) dict();
702 const char *node_type() { return "object"; }
704 virtual void mark_live() {
705 if (!allocator
->mark_live(this, sizeof(*this)))
706 this->items
->mark_live();
709 virtual bool bool_value() { return true; }
711 virtual node
*getattr(const char *key
) {
712 return items
->__getitem__(new(allocator
) string_const(key
));
714 virtual void __setattr__(node
*key
, node
*value
) {
715 items
->__setitem__(key
, value
);
717 virtual bool _eq(node
*rhs
) {
722 class file
: public node
{
727 file(const char *path
, const char *mode
) {
728 f
= fopen(path
, mode
);
730 error("%s: file not found", path
);
732 const char *node_type() { return "file"; }
736 node
*read(int_t len
) {
737 static char buf
[64*1024];
738 size_t ret
= fread(buf
, 1, len
, this->f
);
739 std::string
s(buf
, ret
);
740 return new(allocator
) string_const(s
);
743 virtual bool is_file() { return true; }
746 typedef node
*(*fptr
)(context
*globals
, context
*parent_ctx
, list
*args
, dict
*kwargs
);
748 class bound_method
: public node
{
754 bound_method(node
*self
, node
*function
) {
756 this->function
= function
;
758 const char *node_type() { return "bound_method"; }
760 virtual void mark_live() {
761 if (!allocator
->mark_live(this, sizeof(*this))) {
762 this->self
->mark_live();
763 this->function
->mark_live();
767 virtual bool is_function() { return true; } // XXX is it?
769 virtual node
*__call__(context
*globals
, context
*ctx
, list
*args
, dict
*kwargs
) {
770 if (!args
->is_list())
771 error("call with non-list args?");
772 ((list
*)args
)->prepend(this->self
);
773 return this->function
->__call__(globals
, ctx
, args
, kwargs
);
777 class function_def
: public node
{
782 function_def(fptr base_function
) {
783 this->base_function
= base_function
;
785 const char *node_type() { return "function"; }
789 virtual bool is_function() { return true; }
791 virtual node
*__call__(context
*globals
, context
*ctx
, list
*args
, dict
*kwargs
) {
792 return this->base_function(globals
, ctx
, args
, kwargs
);
796 class class_def
: public node
{
802 class_def(std::string name
, void (*creator
)(class_def
*)) {
804 this->items
= new(allocator
) dict();
807 const char *node_type() { return "class"; }
809 virtual void mark_live() {
810 if (!allocator
->mark_live(this, sizeof(*this)))
811 this->items
->mark_live();
814 node
*load(const char *name
) {
815 return items
->__getitem__(new(allocator
) string_const(name
));
817 void store(const char *name
, node
*value
) {
818 items
->__setitem__(new(allocator
) string_const(name
), value
);
821 virtual node
*__call__(context
*globals
, context
*ctx
, list
*args
, dict
*kwargs
) {
822 node
*init
= this->load("__init__");
823 node
*obj
= new(allocator
) object();
825 obj
->__setattr__(new(allocator
) string_const("__class__"), this);
827 // Create bound methods
828 for (node_dict::iterator i
= items
->begin(); i
!= items
->end(); i
++)
829 if (i
->second
.second
->is_function())
830 obj
->__setattr__(i
->second
.first
, new(allocator
) bound_method(obj
, i
->second
.second
));
832 ((list
*)args
)->prepend(obj
);
833 context
*call_ctx
= new(allocator
) context(ctx
);
834 init
->__call__(globals
, call_ctx
, args
, kwargs
);
837 virtual node
*getattr(const char *attr
) {
838 return this->load(attr
);
842 class class_def_singleton
: public class_def
{
844 class_def_singleton(std::string name
, void (*creator
)(class_def
*)) : class_def(name
, creator
) { }
846 MARK_LIVE_SINGLETON_FN
849 bool_const
bool_singleton_True(true);
850 bool_const
bool_singleton_False(false);
851 none_const
none_singleton(0);
853 inline node
*create_bool_const(bool b
) {
854 return b
? &bool_singleton_True
: &bool_singleton_False
;
857 // Silly builtin classes
858 void _int__create_(class_def
*ctx
) {
861 void _str__create_(class_def
*ctx
) {
864 class_def_singleton
builtin_class_int("int", _int__create_
);
865 class_def_singleton
builtin_class_str("str", _str__create_
);
867 node
*node::__getattr__(node
*key
) {
868 if (!key
->is_string())
869 error("getattr with non-string");
870 return this->getattr(key
->string_value().c_str());
873 node
*node::__hash__() {
874 return new(allocator
) int_const(this->hash());
877 node
*node::__len__() {
878 return new(allocator
) int_const(this->len());
881 node
*node::__not__() {
882 return create_bool_const(!this->bool_value());
885 node
*node::__is__(node
*rhs
) {
886 return create_bool_const(this == rhs
);
889 node
*node::__isnot__(node
*rhs
) {
890 return create_bool_const(this != rhs
);
893 node
*node::__repr__() {
894 return new(allocator
) string_const(this->repr());
897 node
*node::__str__() {
898 return new(allocator
) string_const(this->str());
901 bool none_const::_eq(node
*rhs
) {
902 return (this == rhs
);
905 node
*int_const::getattr(const char *key
) {
906 if (!strcmp(key
, "__class__"))
907 return &builtin_class_int
;
908 error("int has no attribute %s", key
);
912 std::string
int_const::repr() {
914 sprintf(buf
, "%" PRId64
, this->value
);
915 return std::string(buf
);
918 std::string
bool_const::repr() {
919 return std::string(this->value
? "True" : "False");
922 node
*list::__add__(node
*rhs
) {
924 error("list add error");
925 list
*plist
= new(allocator
) list();
926 node_list
*rhs_list
= rhs
->list_value();
927 for (node_list::iterator i
= this->begin(); i
!= this->end(); i
++)
929 for (node_list::iterator i
= rhs_list
->begin(); i
!= rhs_list
->end(); i
++)
934 node
*list::__mul__(node
*rhs
) {
935 if (!rhs
->is_int_const())
936 error("list mul error");
937 list
*plist
= new(allocator
) list();
938 for (int_t x
= rhs
->int_value(); x
> 0; x
--)
939 for (node_list::iterator i
= this->begin(); i
!= this->end(); i
++)
944 node
*list::getattr(const char *key
) {
945 if (!strcmp(key
, "append"))
946 return new(allocator
) bound_method(this, new(allocator
) function_def(builtin_list_append
));
947 else if (!strcmp(key
, "index"))
948 return new(allocator
) bound_method(this, new(allocator
) function_def(builtin_list_index
));
949 else if (!strcmp(key
, "pop"))
950 return new(allocator
) bound_method(this, new(allocator
) function_def(builtin_list_pop
));
951 error("list has no attribute %s", key
);
955 node
*dict::getattr(const char *key
) {
956 if (!strcmp(key
, "get"))
957 return new(allocator
) bound_method(this, new(allocator
) function_def(builtin_dict_get
));
958 else if (!strcmp(key
, "keys"))
959 return new(allocator
) bound_method(this, new(allocator
) function_def(builtin_dict_keys
));
960 error("dict has no attribute %s", key
);
964 node
*set::getattr(const char *key
) {
965 if (!strcmp(key
, "add"))
966 return new(allocator
) bound_method(this, new(allocator
) function_def(builtin_set_add
));
967 error("set has no attribute %s", key
);
971 node
*string_const::getattr(const char *key
) {
972 if (!strcmp(key
, "__class__"))
973 return &builtin_class_str
;
974 else if (!strcmp(key
, "join"))
975 return new(allocator
) bound_method(this, new(allocator
) function_def(builtin_str_join
));
976 else if (!strcmp(key
, "upper"))
977 return new(allocator
) bound_method(this, new(allocator
) function_def(builtin_str_upper
));
978 else if (!strcmp(key
, "startswith"))
979 return new(allocator
) bound_method(this, new(allocator
) function_def(builtin_str_startswith
));
980 error("str has no attribute %s", key
);
984 // This entire function is very stupidly implemented.
985 node
*string_const::__mod__(node
*rhs
) {
986 std::ostringstream new_string
;
988 if (!rhs
->is_list()) {
989 list
*l
= new(allocator
) list();
994 for (const char *c
= value
.c_str(); *c
; c
++) {
996 char fmt_buf
[64], buf
[64];
1000 // Copy over formatting data: only numbers allowed as modifiers now
1001 while (*c
&& isdigit(*c
))
1004 if ((unsigned)(fmt
- fmt_buf
) >= sizeof(buf
))
1005 error("I do believe you've made a terrible mistake whilst formatting a string!");
1006 if (args
>= rhs
->len())
1007 error("not enough arguments for string format");
1008 node
*arg
= rhs
->__getitem__(args
++);
1012 sprintf(buf
, fmt_buf
, arg
->str().c_str());
1014 else if (*c
== 'd' || *c
== 'i' || *c
== 'X') {
1017 sprintf(buf
, fmt_buf
, arg
->int_value());
1019 else if (*c
== 'c') {
1023 if (arg
->is_string())
1024 char_value
= (unsigned char)arg
->string_value()[0];
1026 char_value
= arg
->int_value();
1027 sprintf(buf
, fmt_buf
, char_value
);
1030 error("bad format specifier '%c' in \"%s\"", *c
, value
.c_str());
1036 return new(allocator
) string_const(new_string
.str());
1039 node
*string_const::__add__(node
*rhs
) {
1040 if (!rhs
->is_string())
1041 error("bad argument to str.add");
1042 std::string new_string
= this->value
+ rhs
->string_value();
1043 return new(allocator
) string_const(new_string
);
1046 node
*string_const::__mul__(node
*rhs
) {
1047 if (!rhs
->is_int_const() || rhs
->int_value() < 0)
1048 error("bad argument to str.mul");
1049 std::string new_string
;
1050 for (int_t i
= 0; i
< rhs
->int_value(); i
++)
1051 new_string
+= this->value
;
1052 return new(allocator
) string_const(new_string
);
1055 #define NO_KWARGS(name) \
1056 if (kwargs->len()) \
1057 error(name "() does not take keyword arguments")
1059 node
*builtin_dict(context
*globals
, context
*ctx
, list
*args
, dict
*kwargs
) {
1062 error("too many arguments to dict()");
1063 return new(allocator
) dict();
1066 node
*builtin_dict_get(context
*globals
, context
*ctx
, list
*args
, dict
*kwargs
) {
1067 if (args
->len() != 3) // just assume 3 args for now...
1068 error("bad number of arguments to dict.get()");
1069 node
*self
= args
->__getitem__(0);
1070 node
*key
= args
->__getitem__(1);
1072 node
*value
= ((dict
*)self
)->lookup(key
);
1074 value
= args
->__getitem__(2);
1079 node
*builtin_dict_keys(context
*globals
, context
*ctx
, list
*args
, dict
*kwargs
) {
1080 if (args
->len() != 1)
1081 error("bad number of arguments to dict.keys()");
1082 dict
*self
= (dict
*)args
->__getitem__(0);
1084 list
*plist
= new(allocator
) list();
1085 for (node_dict::iterator i
= self
->begin(); i
!= self
->end(); i
++)
1086 plist
->append(i
->second
.first
);
1091 node
*builtin_fread(context
*globals
, context
*ctx
, list
*args
, dict
*kwargs
) {
1092 node
*f
= args
->__getitem__(0);
1093 node
*len
= args
->__getitem__(1);
1094 if (!f
->is_file() || !len
->is_int_const())
1095 error("bad arguments to fread()");
1096 return ((file
*)f
)->read(len
->int_value());
1099 node
*builtin_isinstance(context
*globals
, context
*ctx
, list
*args
, dict
*kwargs
) {
1100 node
*obj
= args
->__getitem__(0);
1101 node
*arg_class
= args
->__getitem__(1);
1103 node
*obj_class
= obj
->getattr("__class__");
1104 return create_bool_const(obj_class
== arg_class
);
1107 node
*builtin_len(context
*globals
, context
*ctx
, list
*args
, dict
*kwargs
) {
1108 return args
->__getitem__(0)->__len__();
1111 node
*builtin_list(context
*globals
, context
*ctx
, list
*args
, dict
*kwargs
) {
1114 error("too many arguments to list()");
1115 return new(allocator
) list();
1118 node
*builtin_list_append(context
*globals
, context
*ctx
, list
*args
, dict
*kwargs
) {
1119 node
*self
= args
->__getitem__(0);
1120 node
*item
= args
->__getitem__(1);
1122 ((list
*)self
)->append(item
);
1124 return &none_singleton
;
1127 node
*builtin_list_index(context
*globals
, context
*ctx
, list
*args
, dict
*kwargs
) {
1128 if (args
->len() != 2)
1129 error("bad number of arguments to list.index()");
1130 node
*self
= args
->__getitem__(0);
1131 node
*key
= args
->__getitem__(1);
1133 for (int_t i
= 0; i
< self
->len(); i
++)
1134 if (self
->__getitem__(i
)->_eq(key
))
1135 return new(allocator
) int_const(i
);
1136 error("item not found in list");
1137 return &none_singleton
;
1140 node
*builtin_list_pop(context
*globals
, context
*ctx
, list
*args
, dict
*kwargs
) {
1141 list
*self
= (list
*)args
->__getitem__(0);
1146 node
*builtin_open(context
*globals
, context
*ctx
, list
*args
, dict
*kwargs
) {
1147 node
*path
= args
->__getitem__(0);
1148 node
*mode
= args
->__getitem__(1);
1149 if (!path
->is_string() || !mode
->is_string())
1150 error("bad arguments to open()");
1151 file
*f
= new(allocator
) file(path
->string_value().c_str(), mode
->string_value().c_str());
1155 node
*builtin_ord(context
*globals
, context
*ctx
, list
*args
, dict
*kwargs
) {
1156 node
*arg
= args
->__getitem__(0);
1157 if (!arg
->is_string() || arg
->len() != 1)
1158 error("bad arguments to ord()");
1159 return new(allocator
) int_const((unsigned char)arg
->string_value()[0]);
1162 node
*builtin_print(context
*globals
, context
*ctx
, list
*args
, dict
*kwargs
) {
1163 std::string new_string
;
1164 for (int_t i
= 0; i
< args
->len(); i
++) {
1167 node
*s
= args
->__getitem__(i
);
1168 new_string
+= s
->str();
1170 printf("%s\n", new_string
.c_str());
1171 return &none_singleton
;
1174 node
*builtin_print_nonl(context
*globals
, context
*ctx
, list
*args
, dict
*kwargs
) {
1175 node
*s
= args
->__getitem__(0);
1176 printf("%s", s
->str().c_str());
1177 return &none_singleton
;
1180 node
*builtin_range(context
*globals
, context
*ctx
, list
*args
, dict
*kwargs
) {
1181 list
*new_list
= new(allocator
) list();
1182 int_t start
= 0, end
, step
= 1;
1184 if (args
->len() == 1)
1185 end
= args
->__getitem__(0)->int_value();
1186 else if (args
->len() == 2) {
1187 start
= args
->__getitem__(0)->int_value();
1188 end
= args
->__getitem__(1)->int_value();
1190 else if (args
->len() == 3) {
1191 start
= args
->__getitem__(0)->int_value();
1192 end
= args
->__getitem__(1)->int_value();
1193 step
= args
->__getitem__(2)->int_value();
1196 error("too many arguments to range()");
1198 for (int_t s
= start
; step
> 0 ? (s
< end
) : (s
> end
); s
+= step
)
1199 new_list
->append(new(allocator
) int_const(s
));
1203 node
*builtin_reversed(context
*globals
, context
*ctx
, list
*args
, dict
*kwargs
) {
1204 node
*item
= args
->__getitem__(0);
1205 if (!item
->is_list())
1206 error("cannot call reversed on non-list");
1207 list
*plist
= (list
*)item
;
1210 new_list
.resize(plist
->len());
1211 std::reverse_copy(plist
->begin(), plist
->end(), new_list
.begin());
1213 return new(allocator
) list(new_list
);
1216 node
*builtin_set(context
*globals
, context
*ctx
, list
*args
, dict
*kwargs
) {
1219 error("too many arguments to set()");
1220 return new(allocator
) set();
1223 node
*builtin_set_add(context
*globals
, context
*ctx
, list
*args
, dict
*kwargs
) {
1224 node
*self
= args
->__getitem__(0);
1225 node
*item
= args
->__getitem__(1);
1227 ((set
*)self
)->add(item
);
1229 return &none_singleton
;
1232 bool compare_nodes(node
*lhs
, node
*rhs
) {
1233 return lhs
->_lt(rhs
);
1236 node
*builtin_sorted(context
*globals
, context
*ctx
, list
*args
, dict
*kwargs
) {
1237 node
*item
= args
->__getitem__(0);
1238 if (!item
->is_list())
1239 error("cannot call sorted on non-list");
1240 list
*plist
= (list
*)item
;
1243 new_list
.resize(plist
->len());
1244 std::copy(plist
->begin(), plist
->end(), new_list
.begin());
1245 std::stable_sort(new_list
.begin(), new_list
.end(), compare_nodes
);
1247 return new(allocator
) list(new_list
);
1250 node
*builtin_str_join(context
*globals
, context
*ctx
, list
*args
, dict
*kwargs
) {
1251 node
*self
= args
->__getitem__(0);
1252 node
*item
= args
->__getitem__(1);
1253 if (!self
->is_string() || !item
->is_list())
1254 error("bad arguments to str.join()");
1256 list
*joined
= (list
*)item
;
1258 for (node_list::iterator i
= joined
->begin(); i
!= joined
->end(); i
++) {
1260 if (i
+ 1 != joined
->end())
1261 s
+= self
->string_value();
1263 return new(allocator
) string_const(s
);
1266 node
*builtin_str_upper(context
*globals
, context
*ctx
, list
*args
, dict
*kwargs
) {
1267 node
*self
= args
->__getitem__(0);
1268 if (!self
->is_string())
1269 error("bad argument to str.upper()");
1270 string_const
*str
= (string_const
*)self
;
1272 std::string new_string
;
1273 for (std::string::iterator c
= str
->begin(); c
!= str
->end(); c
++)
1274 new_string
+= toupper(*c
);
1276 return new(allocator
) string_const(new_string
);
1279 node
*builtin_str_startswith(context
*globals
, context
*ctx
, list
*args
, dict
*kwargs
) {
1280 node
*self
= args
->__getitem__(0);
1281 node
*prefix
= args
->__getitem__(1);
1282 if (!self
->is_string() || !prefix
->is_string())
1283 error("bad arguments to str.startswith()");
1285 std::string s1
= self
->string_value();
1286 std::string s2
= prefix
->string_value();
1287 return create_bool_const(s1
.compare(0, s2
.size(), s2
) == 0);
1290 node
*builtin_zip(context
*globals
, context
*ctx
, list
*args
, dict
*kwargs
) {
1291 if (args
->len() != 2)
1292 error("bad arguments to zip()");
1293 node
*list1
= args
->__getitem__(0);
1294 node
*list2
= args
->__getitem__(1);
1296 if (!list1
->is_list() || !list2
->is_list() || list1
->len() != list2
->len())
1297 error("bad arguments to zip()");
1299 list
*plist
= new(allocator
) list();
1300 for (int_t i
= 0; i
< list1
->len(); i
++) {
1301 list
*pair
= new(allocator
) list();
1302 pair
->append(list1
->__getitem__(i
));
1303 pair
->append(list2
->__getitem__(i
));
1304 plist
->append(pair
);
1310 void init_context(context
*ctx
, int_t argc
, char **argv
) {
1311 ctx
->store("dict", new(allocator
) function_def(builtin_dict
));
1312 ctx
->store("fread", new(allocator
) function_def(builtin_fread
));
1313 ctx
->store("len", new(allocator
) function_def(builtin_len
));
1314 ctx
->store("isinstance", new(allocator
) function_def(builtin_isinstance
));
1315 ctx
->store("list", new(allocator
) function_def(builtin_list
));
1316 ctx
->store("open", new(allocator
) function_def(builtin_open
));
1317 ctx
->store("ord", new(allocator
) function_def(builtin_ord
));
1318 ctx
->store("print", new(allocator
) function_def(builtin_print
));
1319 ctx
->store("print_nonl", new(allocator
) function_def(builtin_print_nonl
));
1320 ctx
->store("range", new(allocator
) function_def(builtin_range
));
1321 ctx
->store("reversed", new(allocator
) function_def(builtin_reversed
));
1322 ctx
->store("set", new(allocator
) function_def(builtin_set
));
1323 ctx
->store("sorted", new(allocator
) function_def(builtin_sorted
));
1324 ctx
->store("zip", new(allocator
) function_def(builtin_zip
));
1326 ctx
->store("int", &builtin_class_int
);
1327 ctx
->store("str", &builtin_class_str
);
1329 ctx
->store("__name__", new(allocator
) string_const("__main__"));
1330 list
*plist
= new(allocator
) list();
1331 for (int_t a
= 0; a
< argc
; a
++)
1332 plist
->append(new(allocator
) string_const(argv
[a
]));
1333 ctx
->store("__args__", plist
);
1336 void collect_garbage(context
*ctx
, node
*ret_val
) {
1337 static int gc_tick
= 0;
1338 if (++gc_tick
> 128) {
1341 allocator
->mark_dead();
1343 ctx
->mark_live(ret_val
!= NULL
);
1346 ret_val
->mark_live();