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_get(context
*globals
, context
*ctx
, list
*args
, dict
*kwargs
);
62 node
*builtin_dict_keys(context
*globals
, context
*ctx
, list
*args
, dict
*kwargs
);
63 node
*builtin_list_append(context
*globals
, context
*ctx
, list
*args
, dict
*kwargs
);
64 node
*builtin_list_index(context
*globals
, context
*ctx
, list
*args
, dict
*kwargs
);
65 node
*builtin_list_pop(context
*globals
, context
*ctx
, list
*args
, dict
*kwargs
);
66 node
*builtin_set_add(context
*globals
, context
*ctx
, list
*args
, dict
*kwargs
);
67 node
*builtin_str_join(context
*globals
, context
*ctx
, list
*args
, dict
*kwargs
);
68 node
*builtin_str_split(context
*globals
, context
*ctx
, list
*args
, dict
*kwargs
);
69 node
*builtin_str_upper(context
*globals
, context
*ctx
, list
*args
, dict
*kwargs
);
70 node
*builtin_str_startswith(context
*globals
, context
*ctx
, list
*args
, dict
*kwargs
);
72 inline node
*create_bool_const(bool b
);
78 virtual const char *node_type() { return "node"; }
80 virtual void mark_live() { error("mark_live unimplemented for %s", this->node_type()); }
81 #define MARK_LIVE_FN \
82 virtual void mark_live() { allocator->mark_live(this, sizeof(*this)); }
83 #define MARK_LIVE_SINGLETON_FN virtual void mark_live() { }
85 virtual bool is_bool() { return false; }
86 virtual bool is_dict() { return false; }
87 virtual bool is_file() { return false; }
88 virtual bool is_function() { return false; }
89 virtual bool is_int_const() { return false; }
90 virtual bool is_list() { return false; }
91 virtual bool is_none() { return false; }
92 virtual bool is_set() { return false; }
93 virtual bool is_string() { return false; }
94 virtual bool bool_value() { error("bool_value unimplemented for %s", this->node_type()); return false; }
95 virtual int_t
int_value() { error("int_value unimplemented for %s", this->node_type()); return 0; }
96 virtual std::string
string_value() { error("string_value unimplemented for %s", this->node_type()); return NULL
; }
97 virtual node_list
*list_value() { error("list_value unimplemented for %s", this->node_type()); return NULL
; }
99 #define UNIMP_OP(NAME) \
100 virtual node *__##NAME##__(node *rhs) { error(#NAME " unimplemented for %s", this->node_type()); return NULL; }
116 #define UNIMP_CMP_OP(NAME) \
117 virtual bool _##NAME(node *rhs) { error(#NAME " unimplemented for %s", this->node_type()); return false; } \
118 node *__##NAME##__(node *rhs) { return create_bool_const(this->_##NAME(rhs)); }
129 #define UNIMP_UNOP(NAME) \
130 virtual node *__##NAME##__() { error(#NAME " unimplemented for %s", this->node_type()); return NULL; }
138 node
*__getattr__(node
*rhs
);
140 node
*__is__(node
*rhs
);
141 node
*__isnot__(node
*rhs
);
145 virtual node
*__ncontains__(node
*rhs
) { return this->__contains__(rhs
)->__not__(); }
147 virtual node
*__call__(context
*globals
, context
*ctx
, list
*args
, dict
*kwargs
) { error("call unimplemented for %s", this->node_type()); return NULL
; }
148 virtual void __delitem__(node
*rhs
) { error("delitem unimplemented for %s", this->node_type()); }
149 virtual node
*__getitem__(node
*rhs
) { error("getitem unimplemented for %s", this->node_type()); return NULL
; }
150 virtual node
*__getitem__(int index
) { error("getitem unimplemented for %s", this->node_type()); return NULL
; }
151 virtual node
*__iter__() { error("iter unimplemented for %s", this->node_type()); }
152 virtual node
*next() { error("next unimplemented for %s", this->node_type()); }
153 virtual void __setattr__(node
*rhs
, node
*key
) { error("setattr unimplemented for %s", this->node_type()); }
154 virtual void __setitem__(node
*key
, node
*value
) { error("setitem unimplemented for %s", this->node_type()); }
155 virtual node
*__slice__(node
*start
, node
*end
, node
*step
) { error("slice unimplemented for %s", this->node_type()); return NULL
; }
157 // unwrapped versions
158 virtual int_t
len() { error("len unimplemented for %s", this->node_type()); return 0; }
159 virtual node
*getattr(const char *rhs
) { error("getattr unimplemented (%s) for %s", rhs
, this->node_type()); return NULL
; }
160 virtual int_t
hash() { error("hash unimplemented for %s", this->node_type()); return 0; }
161 virtual std::string
repr() { error("repr unimplemented for %s", this->node_type()); return NULL
; }
162 virtual std::string
str() { return repr(); }
167 symbol_table symbols
;
172 this->parent_ctx
= NULL
;
174 context(context
*parent_ctx
) {
175 this->parent_ctx
= parent_ctx
;
178 void mark_live(bool free_ctx
) {
180 for (symbol_table::const_iterator i
= this->symbols
.begin(); i
!= this->symbols
.end(); i
++)
181 i
->second
->mark_live();
182 if (this->parent_ctx
)
183 this->parent_ctx
->mark_live(false);
186 void store(const char *name
, node
*obj
) {
187 this->symbols
[name
] = obj
;
189 node
*load(const char *name
) {
190 symbol_table::const_iterator v
= this->symbols
.find(name
);
191 if (v
== this->symbols
.end())
192 error("cannot find '%s' in symbol table", name
);
196 for (symbol_table::const_iterator i
= this->symbols
.begin(); i
!= this->symbols
.end(); i
++)
197 if (i
->second
->is_int_const())
198 printf("symbol['%s'] = int(%" PRId64
");\n", i
->first
, i
->second
->int_value());
200 printf("symbol['%s'] = %p;\n", i
->first
, i
->second
);
204 class none_const
: public node
{
206 // For some reason this causes errors without an argument to the constructor...
207 none_const(int_t value
) { }
208 const char *node_type() { return "none"; }
210 MARK_LIVE_SINGLETON_FN
212 virtual bool is_none() { return true; }
213 virtual bool bool_value() { return false; }
215 virtual bool _eq(node
*rhs
);
216 virtual int_t
hash() { return 0; }
217 virtual std::string
repr() { return std::string("None"); }
220 class int_const
: public node
{
225 int_const(int_t value
) {
228 const char *node_type() { return "int"; }
232 virtual bool is_int_const() { return true; }
233 virtual int_t
int_value() { return this->value
; }
234 virtual bool bool_value() { return this->value
!= 0; }
236 #define INT_OP(NAME, OP) \
237 virtual int_t _##NAME(node *rhs) { \
238 return this->int_value() OP rhs->int_value(); \
240 virtual node *__##NAME##__(node *rhs) { \
241 return new(allocator) int_const(this->_##NAME(rhs)); \
254 #define CMP_OP(NAME, OP) \
255 virtual bool _##NAME(node *rhs) { \
256 return this->int_value() OP rhs->int_value(); \
266 #define INT_UNOP(NAME, OP) \
267 virtual node *__##NAME##__() { \
268 return new(allocator) int_const(OP this->int_value()); \
274 virtual int_t
hash() { return this->value
; }
275 virtual node
*getattr(const char *key
);
276 virtual std::string
repr();
279 class int_const_singleton
: public int_const
{
281 int_const_singleton(int_t value
) : int_const(value
) { }
283 MARK_LIVE_SINGLETON_FN
286 class bool_const
: public node
{
291 bool_const(bool value
) {
294 const char *node_type() { return "bool"; }
296 MARK_LIVE_SINGLETON_FN
298 virtual bool is_bool() { return true; }
299 virtual bool bool_value() { return this->value
; }
300 virtual int_t
int_value() { return (int_t
)this->value
; }
302 #define BOOL_AS_INT_OP(NAME, OP) \
303 virtual node *__##NAME##__(node *rhs) { \
304 if (rhs->is_int_const() || rhs->is_bool()) \
305 return new(allocator) int_const(this->int_value() OP rhs->int_value()); \
306 error(#NAME " error in bool"); \
309 BOOL_AS_INT_OP(add
, +)
310 BOOL_AS_INT_OP(floordiv
, /)
311 BOOL_AS_INT_OP(lshift
, <<)
312 BOOL_AS_INT_OP(mod
, %)
313 BOOL_AS_INT_OP(mul
, *)
314 BOOL_AS_INT_OP(rshift
, >>)
315 BOOL_AS_INT_OP(sub
, -)
317 #define BOOL_INT_CHECK_OP(NAME, OP) \
318 virtual node *__##NAME##__(node *rhs) { \
319 if (rhs->is_bool()) \
320 return new(allocator) bool_const((bool)(this->int_value() OP rhs->int_value())); \
321 else if (rhs->is_int_const()) \
322 return new(allocator) int_const(this->int_value() OP rhs->int_value()); \
323 error(#NAME " error in bool"); \
327 BOOL_INT_CHECK_OP(and, &)
328 BOOL_INT_CHECK_OP(or, |)
329 BOOL_INT_CHECK_OP(xor, ^)
331 #define BOOL_OP(NAME, OP) \
332 virtual bool _##NAME(node *rhs) { \
333 if (rhs->is_int_const() || rhs->is_bool()) \
334 return this->int_value() OP rhs->int_value(); \
335 error(#NAME " error in bool"); \
345 virtual int_t
hash() { return (int_t
)this->value
; }
346 virtual std::string
repr();
349 class string_const
: public node
{
351 class str_iter
: public node
{
353 string_const
*parent
;
354 std::string::iterator it
;
357 str_iter(string_const
*s
) {
359 it
= s
->value
.begin();
361 const char *node_type() { return "str_iter"; }
363 virtual void mark_live() {
364 if (!allocator
->mark_live(this, sizeof(*this)))
365 this->parent
->mark_live();
368 virtual node
*next() {
369 if (this->it
== this->parent
->value
.end())
375 return new(allocator
) string_const(ret
);
382 string_const(std::string value
) {
385 const char *node_type() { return "str"; }
389 virtual bool is_string() { return true; }
390 virtual std::string
string_value() { return this->value
; }
391 virtual bool bool_value() { return this->len() != 0; }
393 std::string::iterator
begin() { return value
.begin(); }
394 std::string::iterator
end() { return value
.end(); }
396 #define STRING_OP(NAME, OP) \
397 virtual bool _##NAME(node *rhs) { \
398 if (rhs->is_string()) \
399 return this->string_value() OP rhs->string_value(); \
400 error(#NAME " unimplemented"); \
411 virtual node
*__mod__(node
*rhs
);
412 virtual node
*__add__(node
*rhs
);
413 virtual node
*__mul__(node
*rhs
);
415 virtual node
*getattr(const char *key
);
417 virtual node
*__getitem__(node
*rhs
) {
418 if (!rhs
->is_int_const()) {
419 error("getitem unimplemented");
422 return new(allocator
) string_const(value
.substr(rhs
->int_value(), 1));
425 virtual int_t
hash() {
426 int_t hashkey
= 14695981039346656037ull;
427 for (std::string::iterator c
= this->begin(); c
!= this->end(); c
++) {
429 hashkey
*= 1099511628211ll;
433 virtual int_t
len() {
434 return value
.length();
436 virtual node
*__slice__(node
*start
, node
*end
, node
*step
) {
437 if ((!start
->is_none() && !start
->is_int_const()) ||
438 (!end
->is_none() && !end
->is_int_const()) ||
439 (!step
->is_none() && !step
->is_int_const()))
440 error("slice error");
441 int_t lo
= start
->is_none() ? 0 : start
->int_value();
442 int_t hi
= end
->is_none() ? value
.length() : end
->int_value();
443 int_t st
= step
->is_none() ? 1 : step
->int_value();
445 error("slice step != 1 not supported for string");
446 return new(allocator
) string_const(this->value
.substr(lo
, hi
- lo
+ 1));
448 virtual std::string
repr() {
449 bool has_single_quotes
= false;
450 bool has_double_quotes
= false;
451 for (std::string::iterator it
= this->begin(); it
!= this->end(); ++it
) {
454 has_single_quotes
= true;
456 has_double_quotes
= true;
458 bool use_double_quotes
= has_single_quotes
&& !has_double_quotes
;
459 std::string
s(use_double_quotes
? "\"" : "'");
460 for (std::string::iterator it
= this->begin(); it
!= this->end(); ++it
) {
470 else if ((c
== '\'') && !use_double_quotes
)
475 s
+= use_double_quotes
? "\"" : "'";
478 virtual std::string
str() { return this->value
; }
479 virtual node
*__iter__() { return new(allocator
) str_iter(this); }
482 class string_const_singleton
: public string_const
{
487 string_const_singleton(std::string value
, int_t hashkey
) : string_const(value
), hashkey(hashkey
) { }
489 MARK_LIVE_SINGLETON_FN
491 virtual int_t
hash() {
492 return this->hashkey
;
496 class list
: public node
{
498 class list_iter
: public node
{
501 node_list::iterator it
;
506 it
= l
->items
.begin();
508 const char *node_type() { return "list_iter"; }
510 virtual void mark_live() {
511 if (!allocator
->mark_live(this, sizeof(*this)))
512 this->parent
->mark_live();
515 virtual node
*next() {
516 if (this->it
== this->parent
->items
.end())
518 node
*ret
= *this->it
;
528 list(node_list
&l
) : items(l
) { }
529 const char *node_type() { return "list"; }
531 virtual void mark_live() {
532 if (!allocator
->mark_live(this, sizeof(*this))) {
533 for (size_t i
= 0; i
< this->items
.size(); i
++)
534 this->items
[i
]->mark_live();
538 void append(node
*obj
) {
539 items
.push_back(obj
);
541 void prepend(node
*obj
) {
542 items
.insert(items
.begin(), obj
);
545 // would be nice if STL wasn't stupid, and this was one line...
546 node
*popped
= items
.back();
550 node_list::iterator
begin() { return items
.begin(); }
551 node_list::iterator
end() { return items
.end(); }
552 int_t
index(int_t base
) {
554 base
= items
.size() + base
;
558 virtual bool is_list() { return true; }
559 virtual node_list
*list_value() { return &items
; }
560 virtual bool bool_value() { return this->len() != 0; }
562 virtual node
*__add__(node
*rhs
);
563 virtual node
*__mul__(node
*rhs
);
565 virtual node
*__contains__(node
*key
) {
567 for (size_t i
= 0; i
< this->items
.size(); i
++)
568 if (this->items
[i
]->_eq(key
)) {
572 return create_bool_const(found
);
574 virtual void __delitem__(node
*rhs
) {
575 if (!rhs
->is_int_const()) {
576 error("delitem unimplemented");
579 node_list::iterator f
= items
.begin() + this->index(rhs
->int_value());
582 virtual node
*__getitem__(int idx
) {
583 return this->items
[this->index(idx
)];
585 virtual node
*__getitem__(node
*rhs
) {
586 if (!rhs
->is_int_const()) {
587 error("getitem unimplemented");
590 return this->__getitem__(rhs
->int_value());
592 virtual int_t
len() {
593 return this->items
.size();
595 virtual void __setitem__(node
*key
, node
*value
) {
596 if (!key
->is_int_const())
597 error("error in list.setitem");
598 int_t idx
= key
->int_value();
599 items
[this->index(idx
)] = value
;
601 virtual node
*__slice__(node
*start
, node
*end
, node
*step
) {
602 if ((!start
->is_none() && !start
->is_int_const()) ||
603 (!end
->is_none() && !end
->is_int_const()) ||
604 (!step
->is_none() && !step
->is_int_const()))
605 error("slice error");
606 int_t lo
= start
->is_none() ? 0 : start
->int_value();
607 int_t hi
= end
->is_none() ? items
.size() : end
->int_value();
608 int_t st
= step
->is_none() ? 1 : step
->int_value();
609 list
*new_list
= new(allocator
) list();
610 for (; st
> 0 ? (lo
< hi
) : (lo
> hi
); lo
+= st
)
611 new_list
->append(items
[lo
]);
614 virtual std::string
repr() {
615 std::string new_string
= "[";
617 for (node_list::iterator i
= this->items
.begin(); i
!= this->items
.end(); i
++) {
621 new_string
+= (*i
)->repr();
626 virtual node
*getattr(const char *key
);
627 virtual node
*__iter__() { return new(allocator
) list_iter(this); }
630 class tuple
: public node
{
632 class tuple_iter
: public node
{
635 node_list::iterator it
;
638 tuple_iter(tuple
*t
) {
640 it
= t
->items
.begin();
642 const char *node_type() { return "tuple_iter"; }
644 virtual void mark_live() {
645 if (!allocator
->mark_live(this, sizeof(*this)))
646 this->parent
->mark_live();
649 virtual node
*next() {
650 if (this->it
== this->parent
->items
.end())
652 node
*ret
= *this->it
;
662 tuple(node_list
&l
) : items(l
) { }
663 tuple(int_t n
, node
**items
): items(n
) {
664 for (int_t i
= 0; i
< n
; i
++)
665 this->items
[i
] = items
[i
];
667 const char *node_type() { return "tuple"; }
669 virtual void mark_live() {
670 if (!allocator
->mark_live(this, sizeof(*this))) {
671 for (size_t i
= 0; i
< this->items
.size(); i
++)
672 this->items
[i
]->mark_live();
676 int_t
index(int_t base
) {
678 base
= items
.size() + base
;
682 virtual bool bool_value() { return this->len() != 0; }
684 virtual node
*__contains__(node
*key
) {
686 for (size_t i
= 0; i
< this->items
.size(); i
++)
687 if (this->items
[i
]->_eq(key
)) {
691 return create_bool_const(found
);
693 virtual node
*__getitem__(int idx
) {
694 return this->items
[this->index(idx
)];
696 virtual node
*__getitem__(node
*rhs
) {
697 if (!rhs
->is_int_const()) {
698 error("getitem unimplemented");
701 return this->__getitem__(rhs
->int_value());
703 virtual int_t
len() {
704 return this->items
.size();
706 virtual std::string
repr() {
707 std::string new_string
= "(";
709 for (node_list::iterator i
= this->items
.begin(); i
!= this->items
.end(); i
++) {
713 new_string
+= (*i
)->repr();
715 if (this->items
.size() == 1)
720 virtual node
*__iter__() { return new(allocator
) tuple_iter(this); }
723 class dict
: public node
{
725 class dict_iter
: public node
{
728 node_dict::iterator it
;
733 it
= d
->items
.begin();
735 const char *node_type() { return "dict_iter"; }
737 virtual void mark_live() {
738 if (!allocator
->mark_live(this, sizeof(*this)))
739 this->parent
->mark_live();
742 virtual node
*next() {
743 if (this->it
== this->parent
->items
.end())
745 node
*ret
= this->it
->second
.first
;
755 const char *node_type() { return "dict"; }
757 virtual void mark_live() {
758 if (!allocator
->mark_live(this, sizeof(*this))) {
759 for (node_dict::iterator i
= this->items
.begin(); i
!= this->items
.end(); i
++) {
760 i
->second
.first
->mark_live();
761 i
->second
.second
->mark_live();
766 node
*lookup(node
*key
) {
768 if (key
->is_int_const())
769 hashkey
= key
->int_value();
771 hashkey
= key
->hash();
772 node_dict::const_iterator v
= this->items
.find(hashkey
);
773 if (v
== this->items
.end())
775 node
*k
= v
->second
.first
;
778 return v
->second
.second
;
780 node_dict::iterator
begin() { return items
.begin(); }
781 node_dict::iterator
end() { return items
.end(); }
783 virtual bool is_dict() { return true; }
784 virtual bool bool_value() { return this->len() != 0; }
786 virtual node
*__contains__(node
*key
) {
787 return create_bool_const(this->lookup(key
) != NULL
);
789 virtual node
*__getitem__(node
*key
) {
790 node
*value
= this->lookup(key
);
792 error("cannot find %s in dict", key
->repr().c_str());
795 virtual int_t
len() {
796 return this->items
.size();
798 virtual void __setitem__(node
*key
, node
*value
) {
800 if (key
->is_int_const())
801 hashkey
= key
->int_value();
803 hashkey
= key
->hash();
804 items
[hashkey
] = node_pair(key
, value
);
806 virtual std::string
repr() {
807 std::string new_string
= "{";
809 for (node_dict::iterator i
= this->items
.begin(); i
!= this->items
.end(); i
++) {
813 new_string
+= i
->second
.first
->repr() + ": " + i
->second
.second
->repr();
818 virtual node
*getattr(const char *key
);
819 virtual node
*__iter__() { return new(allocator
) dict_iter(this); }
822 class set
: public node
{
824 class set_iter
: public node
{
827 node_set::iterator it
;
832 it
= s
->items
.begin();
834 const char *node_type() { return "set_iter"; }
836 virtual void mark_live() {
837 if (!allocator
->mark_live(this, sizeof(*this)))
838 this->parent
->mark_live();
841 virtual node
*next() {
842 if (this->it
== this->parent
->items
.end())
844 node
*ret
= this->it
->second
;
854 const char *node_type() { return "set"; }
856 virtual void mark_live() {
857 if (!allocator
->mark_live(this, sizeof(*this))) {
858 for (node_set::iterator i
= this->items
.begin(); i
!= this->items
.end(); i
++)
859 i
->second
->mark_live();
863 node
*lookup(node
*key
) {
865 if (key
->is_int_const())
866 hashkey
= key
->int_value();
868 hashkey
= key
->hash();
869 node_set::const_iterator v
= this->items
.find(hashkey
);
870 if (v
== this->items
.end() || !v
->second
->_eq(key
))
874 void add(node
*key
) {
876 if (key
->is_int_const())
877 hashkey
= key
->int_value();
879 hashkey
= key
->hash();
880 items
[hashkey
] = key
;
883 virtual bool is_set() { return true; }
884 virtual bool bool_value() { return this->len() != 0; }
886 virtual node
*__contains__(node
*key
) {
887 return create_bool_const(this->lookup(key
) != NULL
);
889 virtual int_t
len() {
890 return this->items
.size();
892 virtual std::string
repr() {
893 if (!this->items
.size())
895 std::string new_string
= "{";
897 for (node_set::iterator i
= this->items
.begin(); i
!= this->items
.end(); i
++) {
901 new_string
+= i
->second
->repr();
906 virtual node
*getattr(const char *key
);
907 virtual node
*__iter__() { return new(allocator
) set_iter(this); }
910 class object
: public node
{
916 this->items
= new(allocator
) dict();
918 const char *node_type() { return "object"; }
920 virtual void mark_live() {
921 if (!allocator
->mark_live(this, sizeof(*this)))
922 this->items
->mark_live();
925 virtual bool bool_value() { return true; }
927 virtual node
*getattr(const char *key
) {
928 return items
->__getitem__(new(allocator
) string_const(key
));
930 virtual void __setattr__(node
*key
, node
*value
) {
931 items
->__setitem__(key
, value
);
933 virtual bool _eq(node
*rhs
) {
938 class file
: public node
{
943 file(const char *path
, const char *mode
) {
944 f
= fopen(path
, mode
);
946 error("%s: file not found", path
);
948 const char *node_type() { return "file"; }
952 node
*read(int_t len
) {
953 static char buf
[64*1024];
954 size_t ret
= fread(buf
, 1, len
, this->f
);
955 std::string
s(buf
, ret
);
956 return new(allocator
) string_const(s
);
959 virtual bool is_file() { return true; }
962 class range
: public node
{
964 class range_iter
: public node
{
966 int_t start
, end
, step
;
969 range_iter(range
*r
) {
970 this->start
= r
->start
;
972 this->step
= r
->step
;
974 const char *node_type() { return "range_iter"; }
978 virtual node
*next() {
980 if (this->start
>= this->end
)
984 if (this->start
<= this->end
)
987 node
*ret
= new(allocator
) int_const(this->start
);
988 this->start
+= this->step
;
993 int_t start
, end
, step
;
996 range(int_t start
, int_t end
, int_t step
) {
1001 const char *node_type() { return "range"; }
1005 virtual node
*__iter__() { return new(allocator
) range_iter(this); }
1007 virtual std::string
repr() {
1010 sprintf(buf
, "range(%ld, %ld)", this->start
, this->end
);
1013 sprintf(buf
, "range(%ld, %ld, %ld)", this->start
, this->end
, this->step
);
1019 typedef node
*(*fptr
)(context
*globals
, context
*parent_ctx
, list
*args
, dict
*kwargs
);
1021 class bound_method
: public node
{
1027 bound_method(node
*self
, node
*function
) {
1029 this->function
= function
;
1031 const char *node_type() { return "bound_method"; }
1033 virtual void mark_live() {
1034 if (!allocator
->mark_live(this, sizeof(*this))) {
1035 this->self
->mark_live();
1036 this->function
->mark_live();
1040 virtual bool is_function() { return true; } // XXX is it?
1042 virtual node
*__call__(context
*globals
, context
*ctx
, list
*args
, dict
*kwargs
) {
1043 if (!args
->is_list())
1044 error("call with non-list args?");
1045 ((list
*)args
)->prepend(this->self
);
1046 return this->function
->__call__(globals
, ctx
, args
, kwargs
);
1050 class function_def
: public node
{
1055 function_def(fptr base_function
) {
1056 this->base_function
= base_function
;
1058 const char *node_type() { return "function"; }
1062 virtual bool is_function() { return true; }
1064 virtual node
*__call__(context
*globals
, context
*ctx
, list
*args
, dict
*kwargs
) {
1065 return this->base_function(globals
, ctx
, args
, kwargs
);
1069 class class_def
: public node
{
1075 class_def(std::string name
, void (*creator
)(class_def
*)) {
1077 this->items
= new(allocator
) dict();
1080 const char *node_type() { return "class"; }
1082 virtual void mark_live() {
1083 if (!allocator
->mark_live(this, sizeof(*this)))
1084 this->items
->mark_live();
1087 node
*load(const char *name
) {
1088 return items
->__getitem__(new(allocator
) string_const(name
));
1090 void store(const char *name
, node
*value
) {
1091 items
->__setitem__(new(allocator
) string_const(name
), value
);
1094 virtual node
*__call__(context
*globals
, context
*ctx
, list
*args
, dict
*kwargs
) {
1095 node
*init
= this->load("__init__");
1096 node
*obj
= new(allocator
) object();
1098 obj
->__setattr__(new(allocator
) string_const("__class__"), this);
1100 // Create bound methods
1101 for (node_dict::iterator i
= items
->begin(); i
!= items
->end(); i
++)
1102 if (i
->second
.second
->is_function())
1103 obj
->__setattr__(i
->second
.first
, new(allocator
) bound_method(obj
, i
->second
.second
));
1105 ((list
*)args
)->prepend(obj
);
1106 context
*call_ctx
= new(allocator
) context(ctx
);
1107 init
->__call__(globals
, call_ctx
, args
, kwargs
);
1110 virtual node
*getattr(const char *attr
) {
1111 return this->load(attr
);
1113 virtual std::string
repr() {
1114 return std::string("<class '") + this->name
+ "'>";
1118 bool_const
bool_singleton_True(true);
1119 bool_const
bool_singleton_False(false);
1120 none_const
none_singleton(0);
1122 inline node
*create_bool_const(bool b
) {
1123 return b
? &bool_singleton_True
: &bool_singleton_False
;
1126 #define NO_KWARGS_N_ARGS(name, n_args) \
1127 if (kwargs->len()) \
1128 error(name "() does not take keyword arguments"); \
1129 if (args->len() != n_args) \
1130 error("wrong number of arguments to " name "()")
1132 #define NO_KWARGS_MAX_ARGS(name, max_args) \
1133 if (kwargs->len()) \
1134 error(name "() does not take keyword arguments"); \
1135 if (args->len() > max_args) \
1136 error("too many arguments to " name "()")
1139 #define LIST_BUILTIN_CLASSES(x) \
1152 #define LIST_BUILTIN_CLASS_METHODS(x) \
1162 x(str, startswith) \
1164 class builtin_method_def: public function_def {
1166 builtin_method_def(fptr base_function
): function_def(base_function
) {}
1168 MARK_LIVE_SINGLETON_FN
1171 #define BUILTIN_METHOD(class_name, method_name) builtin_method_def builtin_method_##class_name##_##method_name(builtin_##class_name##_##method_name);
1172 LIST_BUILTIN_CLASS_METHODS(BUILTIN_METHOD
)
1173 #undef BUILTIN_METHOD
1175 void _dummy__create_(class_def
*ctx
) {}
1177 class builtin_class_def_singleton
: public class_def
{
1179 builtin_class_def_singleton(std::string name
): class_def(name
, _dummy__create_
) {}
1181 MARK_LIVE_SINGLETON_FN
1184 class bool_class_def_singleton
: public builtin_class_def_singleton
{
1186 bool_class_def_singleton(): builtin_class_def_singleton("bool") {}
1188 virtual node
*__call__(context
*globals
, context
*ctx
, list
*args
, dict
*kwargs
) {
1189 NO_KWARGS_MAX_ARGS("bool", 1);
1191 return &bool_singleton_False
;
1192 node
*arg
= args
->__getitem__(0);
1193 return create_bool_const(arg
->bool_value());
1197 class dict_class_def_singleton
: public builtin_class_def_singleton
{
1199 dict_class_def_singleton(): builtin_class_def_singleton("dict") {}
1201 virtual node
*getattr(const char *key
) {
1202 if (!strcmp(key
, "get"))
1203 return &builtin_method_dict_get
;
1204 if (!strcmp(key
, "keys"))
1205 return &builtin_method_dict_keys
;
1206 error("dict has no attribute %s", key
);
1210 virtual node
*__call__(context
*globals
, context
*ctx
, list
*args
, dict
*kwargs
) {
1211 NO_KWARGS_N_ARGS("dict", 0);
1212 return new(allocator
) dict();
1216 class enumerate_class_def_singleton
: public builtin_class_def_singleton
{
1218 enumerate_class_def_singleton(): builtin_class_def_singleton("enumerate") {}
1220 virtual node
*__call__(context
*globals
, context
*ctx
, list
*args
, dict
*kwargs
) {
1221 NO_KWARGS_N_ARGS("enumerate", 1);
1222 node
*arg
= args
->__getitem__(0);
1223 node
*iter
= arg
->__iter__();
1224 list
*ret
= new(allocator
) list
;
1226 for (node
*item
= iter
->next(); item
; item
= iter
->next(), i
++) {
1228 pair
[0] = new(allocator
) int_const(i
);
1230 ret
->append(new(allocator
) tuple(2, pair
));
1236 class int_class_def_singleton
: public builtin_class_def_singleton
{
1238 int_class_def_singleton(): builtin_class_def_singleton("int") {}
1240 virtual node
*__call__(context
*globals
, context
*ctx
, list
*args
, dict
*kwargs
) {
1241 NO_KWARGS_MAX_ARGS("int", 1);
1243 return new(allocator
) int_const(0);
1244 node
*arg
= args
->__getitem__(0);
1245 if (arg
->is_int_const())
1247 if (arg
->is_string()) {
1248 std::string s
= arg
->string_value();
1249 return new(allocator
) int_const(atoi(s
.c_str()));
1251 error("don't know how to handle argument to int()");
1255 class list_class_def_singleton
: public builtin_class_def_singleton
{
1257 list_class_def_singleton(): builtin_class_def_singleton("list") {}
1259 virtual node
*getattr(const char *key
) {
1260 if (!strcmp(key
, "append"))
1261 return &builtin_method_list_append
;
1262 if (!strcmp(key
, "index"))
1263 return &builtin_method_list_index
;
1264 if (!strcmp(key
, "pop"))
1265 return &builtin_method_list_pop
;
1266 error("list has no attribute %s", key
);
1269 virtual node
*__call__(context
*globals
, context
*ctx
, list
*args
, dict
*kwargs
) {
1270 NO_KWARGS_MAX_ARGS("list", 1);
1271 list
*ret
= new(allocator
) list();
1274 node
*arg
= args
->__getitem__(0);
1275 node
*iter
= arg
->__iter__();
1276 for (node
*item
= iter
->next(); item
; item
= iter
->next())
1282 class range_class_def_singleton
: public builtin_class_def_singleton
{
1284 range_class_def_singleton(): builtin_class_def_singleton("range") {}
1286 virtual node
*__call__(context
*globals
, context
*ctx
, list
*args
, dict
*kwargs
) {
1287 int_t start
= 0, end
, step
= 1;
1289 if (args
->len() == 1)
1290 end
= args
->__getitem__(0)->int_value();
1291 else if (args
->len() == 2) {
1292 start
= args
->__getitem__(0)->int_value();
1293 end
= args
->__getitem__(1)->int_value();
1295 else if (args
->len() == 3) {
1296 start
= args
->__getitem__(0)->int_value();
1297 end
= args
->__getitem__(1)->int_value();
1298 step
= args
->__getitem__(2)->int_value();
1301 error("too many arguments to range()");
1303 return new(allocator
) range(start
, end
, step
);
1307 class reversed_class_def_singleton
: public builtin_class_def_singleton
{
1309 reversed_class_def_singleton(): builtin_class_def_singleton("reversed") {}
1311 node
*__call__(context
*globals
, context
*ctx
, list
*args
, dict
*kwargs
) {
1312 NO_KWARGS_N_ARGS("reversed", 1);
1313 node
*item
= args
->__getitem__(0);
1314 if (!item
->is_list())
1315 error("cannot call reversed on non-list");
1316 list
*plist
= (list
*)item
;
1319 new_list
.resize(plist
->len());
1320 std::reverse_copy(plist
->begin(), plist
->end(), new_list
.begin());
1322 return new(allocator
) list(new_list
);
1326 class set_class_def_singleton
: public builtin_class_def_singleton
{
1328 set_class_def_singleton(): builtin_class_def_singleton("set") {}
1330 virtual node
*getattr(const char *key
) {
1331 if (!strcmp(key
, "add"))
1332 return &builtin_method_set_add
;
1333 error("set has no attribute %s", key
);
1337 virtual node
*__call__(context
*globals
, context
*ctx
, list
*args
, dict
*kwargs
) {
1338 NO_KWARGS_MAX_ARGS("set", 1);
1339 set
*ret
= new(allocator
) set();
1342 node
*arg
= args
->__getitem__(0);
1343 node
*iter
= arg
->__iter__();
1344 for (node
*item
= iter
->next(); item
; item
= iter
->next())
1350 class str_class_def_singleton
: public builtin_class_def_singleton
{
1352 str_class_def_singleton(): builtin_class_def_singleton("str") {}
1354 virtual node
*getattr(const char *key
) {
1355 if (!strcmp(key
, "join"))
1356 return &builtin_method_str_join
;
1357 if (!strcmp(key
, "split"))
1358 return &builtin_method_str_split
;
1359 if (!strcmp(key
, "upper"))
1360 return &builtin_method_str_upper
;
1361 if (!strcmp(key
, "startswith"))
1362 return &builtin_method_str_startswith
;
1363 error("str has no attribute %s", key
);
1366 virtual node
*__call__(context
*globals
, context
*ctx
, list
*args
, dict
*kwargs
) {
1367 NO_KWARGS_MAX_ARGS("str", 1);
1369 return new(allocator
) string_const("");
1370 node
*arg
= args
->__getitem__(0);
1371 return arg
->__str__();
1375 class tuple_class_def_singleton
: public builtin_class_def_singleton
{
1377 tuple_class_def_singleton(): builtin_class_def_singleton("tuple") {}
1379 virtual node
*__call__(context
*globals
, context
*ctx
, list
*args
, dict
*kwargs
) {
1380 NO_KWARGS_MAX_ARGS("tuple", 1);
1382 return new(allocator
) tuple
;
1383 node
*arg
= args
->__getitem__(0);
1384 node
*iter
= arg
->__iter__();
1386 for (node
*item
= iter
->next(); item
; item
= iter
->next())
1388 return new(allocator
) tuple(l
);
1392 class zip_class_def_singleton
: public builtin_class_def_singleton
{
1394 zip_class_def_singleton(): builtin_class_def_singleton("zip") {}
1396 virtual node
*__call__(context
*globals
, context
*ctx
, list
*args
, dict
*kwargs
) {
1397 NO_KWARGS_N_ARGS("zip", 2);
1398 node
*list1
= args
->__getitem__(0);
1399 node
*list2
= args
->__getitem__(1);
1401 if (!list1
->is_list() || !list2
->is_list() || list1
->len() != list2
->len())
1402 error("bad arguments to zip()");
1404 list
*plist
= new(allocator
) list();
1405 for (int_t i
= 0; i
< list1
->len(); i
++) {
1407 pair
[0] = list1
->__getitem__(i
);
1408 pair
[1] = list2
->__getitem__(i
);
1409 plist
->append(new(allocator
) tuple(2, pair
));
1416 #define BUILTIN_CLASS(name) name##_class_def_singleton builtin_class_##name;
1417 LIST_BUILTIN_CLASSES(BUILTIN_CLASS
)
1418 #undef BUILTIN_CLASS
1420 node
*node::__getattr__(node
*key
) {
1421 if (!key
->is_string())
1422 error("getattr with non-string");
1423 return this->getattr(key
->string_value().c_str());
1426 node
*node::__hash__() {
1427 return new(allocator
) int_const(this->hash());
1430 node
*node::__len__() {
1431 return new(allocator
) int_const(this->len());
1434 node
*node::__not__() {
1435 return create_bool_const(!this->bool_value());
1438 node
*node::__is__(node
*rhs
) {
1439 return create_bool_const(this == rhs
);
1442 node
*node::__isnot__(node
*rhs
) {
1443 return create_bool_const(this != rhs
);
1446 node
*node::__repr__() {
1447 return new(allocator
) string_const(this->repr());
1450 node
*node::__str__() {
1451 return new(allocator
) string_const(this->str());
1454 bool none_const::_eq(node
*rhs
) {
1455 return (this == rhs
);
1458 node
*int_const::getattr(const char *key
) {
1459 if (!strcmp(key
, "__class__"))
1460 return &builtin_class_int
;
1461 error("int has no attribute %s", key
);
1465 std::string
int_const::repr() {
1467 sprintf(buf
, "%" PRId64
, this->value
);
1468 return std::string(buf
);
1471 std::string
bool_const::repr() {
1472 return std::string(this->value
? "True" : "False");
1475 node
*list::__add__(node
*rhs
) {
1476 if (!rhs
->is_list())
1477 error("list add error");
1478 list
*plist
= new(allocator
) list();
1479 node_list
*rhs_list
= rhs
->list_value();
1480 for (node_list::iterator i
= this->begin(); i
!= this->end(); i
++)
1482 for (node_list::iterator i
= rhs_list
->begin(); i
!= rhs_list
->end(); i
++)
1487 node
*list::__mul__(node
*rhs
) {
1488 if (!rhs
->is_int_const())
1489 error("list mul error");
1490 list
*plist
= new(allocator
) list();
1491 for (int_t x
= rhs
->int_value(); x
> 0; x
--)
1492 for (node_list::iterator i
= this->begin(); i
!= this->end(); i
++)
1497 node
*list::getattr(const char *key
) {
1498 if (!strcmp(key
, "__class__"))
1499 return &builtin_class_list
;
1500 return new(allocator
) bound_method(this, builtin_class_list
.getattr(key
));
1503 node
*dict::getattr(const char *key
) {
1504 if (!strcmp(key
, "__class__"))
1505 return &builtin_class_dict
;
1506 return new(allocator
) bound_method(this, builtin_class_dict
.getattr(key
));
1509 node
*set::getattr(const char *key
) {
1510 if (!strcmp(key
, "__class__"))
1511 return &builtin_class_set
;
1512 return new(allocator
) bound_method(this, builtin_class_set
.getattr(key
));
1515 node
*string_const::getattr(const char *key
) {
1516 if (!strcmp(key
, "__class__"))
1517 return &builtin_class_str
;
1518 return new(allocator
) bound_method(this, builtin_class_str
.getattr(key
));
1521 // This entire function is very stupidly implemented.
1522 node
*string_const::__mod__(node
*rhs
) {
1523 std::ostringstream new_string
;
1525 if (!rhs
->is_list()) {
1526 list
*l
= new(allocator
) list();
1531 for (const char *c
= value
.c_str(); *c
; c
++) {
1533 char fmt_buf
[64], buf
[64];
1534 char *fmt
= fmt_buf
;
1537 // Copy over formatting data: only numbers allowed as modifiers now
1538 while (*c
&& isdigit(*c
))
1541 if ((unsigned)(fmt
- fmt_buf
) >= sizeof(buf
))
1542 error("I do believe you've made a terrible mistake whilst formatting a string!");
1543 if (args
>= rhs
->len())
1544 error("not enough arguments for string format");
1545 node
*arg
= rhs
->__getitem__(args
++);
1549 sprintf(buf
, fmt_buf
, arg
->str().c_str());
1551 else if (*c
== 'd' || *c
== 'i' || *c
== 'X') {
1556 sprintf(buf
, fmt_buf
, arg
->int_value());
1558 else if (*c
== 'c') {
1562 if (arg
->is_string())
1563 char_value
= (unsigned char)arg
->string_value()[0];
1565 char_value
= arg
->int_value();
1566 sprintf(buf
, fmt_buf
, char_value
);
1569 error("bad format specifier '%c' in \"%s\"", *c
, value
.c_str());
1575 return new(allocator
) string_const(new_string
.str());
1578 node
*string_const::__add__(node
*rhs
) {
1579 if (!rhs
->is_string())
1580 error("bad argument to str.add");
1581 std::string new_string
= this->value
+ rhs
->string_value();
1582 return new(allocator
) string_const(new_string
);
1585 node
*string_const::__mul__(node
*rhs
) {
1586 if (!rhs
->is_int_const() || rhs
->int_value() < 0)
1587 error("bad argument to str.mul");
1588 std::string new_string
;
1589 for (int_t i
= 0; i
< rhs
->int_value(); i
++)
1590 new_string
+= this->value
;
1591 return new(allocator
) string_const(new_string
);
1594 ////////////////////////////////////////////////////////////////////////////////
1595 // Builtins ////////////////////////////////////////////////////////////////////
1596 ////////////////////////////////////////////////////////////////////////////////
1598 class builtin_function_def
: public function_def
{
1603 builtin_function_def(const char *name
, fptr base_function
): function_def(base_function
) {
1606 const char *node_type() { return "builtin_function"; }
1608 MARK_LIVE_SINGLETON_FN
1610 virtual std::string
repr() {
1611 return std::string("<built-in function ") + this->name
+ ">";
1615 #define LIST_BUILTIN_FUNCTIONS(x) \
1626 node *builtin_dict_get(context *globals, context *ctx, list *args, dict *kwargs) {
1627 NO_KWARGS_N_ARGS("dict.get", 3);
1628 node
*self
= args
->__getitem__(0);
1629 node
*key
= args
->__getitem__(1);
1631 node
*value
= ((dict
*)self
)->lookup(key
);
1633 value
= args
->__getitem__(2);
1638 node
*builtin_dict_keys(context
*globals
, context
*ctx
, list
*args
, dict
*kwargs
) {
1639 NO_KWARGS_N_ARGS("dict.keys", 1);
1640 dict
*self
= (dict
*)args
->__getitem__(0);
1642 list
*plist
= new(allocator
) list();
1643 for (node_dict::iterator i
= self
->begin(); i
!= self
->end(); i
++)
1644 plist
->append(i
->second
.first
);
1649 node
*builtin_fread(context
*globals
, context
*ctx
, list
*args
, dict
*kwargs
) {
1650 NO_KWARGS_N_ARGS("fread", 2);
1651 node
*f
= args
->__getitem__(0);
1652 node
*len
= args
->__getitem__(1);
1653 if (!f
->is_file() || !len
->is_int_const())
1654 error("bad arguments to fread()");
1655 return ((file
*)f
)->read(len
->int_value());
1658 node
*builtin_isinstance(context
*globals
, context
*ctx
, list
*args
, dict
*kwargs
) {
1659 NO_KWARGS_N_ARGS("isinstance", 2);
1660 node
*obj
= args
->__getitem__(0);
1661 node
*arg_class
= args
->__getitem__(1);
1663 node
*obj_class
= obj
->getattr("__class__");
1664 return create_bool_const(obj_class
== arg_class
);
1667 node
*builtin_len(context
*globals
, context
*ctx
, list
*args
, dict
*kwargs
) {
1668 NO_KWARGS_N_ARGS("len", 1);
1669 return args
->__getitem__(0)->__len__();
1672 node
*builtin_list_append(context
*globals
, context
*ctx
, list
*args
, dict
*kwargs
) {
1673 NO_KWARGS_N_ARGS("list.append", 2);
1674 node
*self
= args
->__getitem__(0);
1675 node
*item
= args
->__getitem__(1);
1677 ((list
*)self
)->append(item
);
1679 return &none_singleton
;
1682 node
*builtin_list_index(context
*globals
, context
*ctx
, list
*args
, dict
*kwargs
) {
1683 NO_KWARGS_N_ARGS("list.index", 2);
1684 node
*self
= args
->__getitem__(0);
1685 node
*key
= args
->__getitem__(1);
1687 for (int_t i
= 0; i
< self
->len(); i
++)
1688 if (self
->__getitem__(i
)->_eq(key
))
1689 return new(allocator
) int_const(i
);
1690 error("item not found in list");
1691 return &none_singleton
;
1694 node
*builtin_list_pop(context
*globals
, context
*ctx
, list
*args
, dict
*kwargs
) {
1695 NO_KWARGS_N_ARGS("pop", 1);
1696 list
*self
= (list
*)args
->__getitem__(0);
1701 node
*builtin_open(context
*globals
, context
*ctx
, list
*args
, dict
*kwargs
) {
1702 NO_KWARGS_N_ARGS("open", 2);
1703 node
*path
= args
->__getitem__(0);
1704 node
*mode
= args
->__getitem__(1);
1705 if (!path
->is_string() || !mode
->is_string())
1706 error("bad arguments to open()");
1707 file
*f
= new(allocator
) file(path
->string_value().c_str(), mode
->string_value().c_str());
1711 node
*builtin_ord(context
*globals
, context
*ctx
, list
*args
, dict
*kwargs
) {
1712 NO_KWARGS_N_ARGS("ord", 1);
1713 node
*arg
= args
->__getitem__(0);
1714 if (!arg
->is_string() || arg
->len() != 1)
1715 error("bad arguments to ord()");
1716 return new(allocator
) int_const((unsigned char)arg
->string_value()[0]);
1719 node
*builtin_print(context
*globals
, context
*ctx
, list
*args
, dict
*kwargs
) {
1720 std::string new_string
;
1721 for (int_t i
= 0; i
< args
->len(); i
++) {
1724 node
*s
= args
->__getitem__(i
);
1725 new_string
+= s
->str();
1727 printf("%s\n", new_string
.c_str());
1728 return &none_singleton
;
1731 node
*builtin_print_nonl(context
*globals
, context
*ctx
, list
*args
, dict
*kwargs
) {
1732 NO_KWARGS_N_ARGS("print_nonl", 1);
1733 node
*s
= args
->__getitem__(0);
1734 printf("%s", s
->str().c_str());
1735 return &none_singleton
;
1738 node
*builtin_repr(context
*globals
, context
*ctx
, list
*args
, dict
*kwargs
) {
1739 NO_KWARGS_N_ARGS("repr", 1);
1740 node
*arg
= args
->__getitem__(0);
1741 return arg
->__repr__();
1744 node
*builtin_set_add(context
*globals
, context
*ctx
, list
*args
, dict
*kwargs
) {
1745 NO_KWARGS_N_ARGS("set.add", 2);
1746 node
*self
= args
->__getitem__(0);
1747 node
*item
= args
->__getitem__(1);
1749 ((set
*)self
)->add(item
);
1751 return &none_singleton
;
1754 bool compare_nodes(node
*lhs
, node
*rhs
) {
1755 return lhs
->_lt(rhs
);
1758 node
*builtin_sorted(context
*globals
, context
*ctx
, list
*args
, dict
*kwargs
) {
1759 NO_KWARGS_N_ARGS("sorted", 1);
1760 node
*item
= args
->__getitem__(0);
1761 if (!item
->is_list())
1762 error("cannot call sorted on non-list");
1763 list
*plist
= (list
*)item
;
1766 new_list
.resize(plist
->len());
1767 std::copy(plist
->begin(), plist
->end(), new_list
.begin());
1768 std::stable_sort(new_list
.begin(), new_list
.end(), compare_nodes
);
1770 return new(allocator
) list(new_list
);
1773 node
*builtin_str_join(context
*globals
, context
*ctx
, list
*args
, dict
*kwargs
) {
1774 NO_KWARGS_N_ARGS("str.join", 2);
1775 node
*self
= args
->__getitem__(0);
1776 node
*item
= args
->__getitem__(1);
1777 if (!self
->is_string() || !item
->is_list())
1778 error("bad arguments to str.join()");
1780 list
*joined
= (list
*)item
;
1782 for (node_list::iterator i
= joined
->begin(); i
!= joined
->end(); i
++) {
1784 if (i
+ 1 != joined
->end())
1785 s
+= self
->string_value();
1787 return new(allocator
) string_const(s
);
1790 node
*builtin_str_split(context
*globals
, context
*ctx
, list
*args
, dict
*kwargs
) {
1791 NO_KWARGS_N_ARGS("str.split", 2);
1792 node
*self
= args
->__getitem__(0);
1793 node
*item
= args
->__getitem__(1);
1794 if (!self
->is_string() || !item
->is_string() || (item
->len() != 1))
1795 error("bad argument to str.upper()");
1796 string_const
*str
= (string_const
*)self
;
1797 char split
= item
->string_value()[0];
1798 list
*ret
= new(allocator
) list
;
1800 for (std::string::iterator c
= str
->begin(); c
!= str
->end(); ++c
) {
1802 ret
->append(new(allocator
) string_const(s
));
1809 ret
->append(new(allocator
) string_const(s
));
1813 node
*builtin_str_upper(context
*globals
, context
*ctx
, list
*args
, dict
*kwargs
) {
1814 NO_KWARGS_N_ARGS("str.upper", 1);
1815 node
*self
= args
->__getitem__(0);
1816 if (!self
->is_string())
1817 error("bad argument to str.upper()");
1818 string_const
*str
= (string_const
*)self
;
1820 std::string new_string
;
1821 for (std::string::iterator c
= str
->begin(); c
!= str
->end(); c
++)
1822 new_string
+= toupper(*c
);
1824 return new(allocator
) string_const(new_string
);
1827 node
*builtin_str_startswith(context
*globals
, context
*ctx
, list
*args
, dict
*kwargs
) {
1828 NO_KWARGS_N_ARGS("str.startswith", 2);
1829 node
*self
= args
->__getitem__(0);
1830 node
*prefix
= args
->__getitem__(1);
1831 if (!self
->is_string() || !prefix
->is_string())
1832 error("bad arguments to str.startswith()");
1834 std::string s1
= self
->string_value();
1835 std::string s2
= prefix
->string_value();
1836 return create_bool_const(s1
.compare(0, s2
.size(), s2
) == 0);
1839 #define BUILTIN_FUNCTION(name) builtin_function_def builtin_function_##name(#name, builtin_##name);
1840 LIST_BUILTIN_FUNCTIONS(BUILTIN_FUNCTION
)
1841 #undef BUILTIN_FUNCTION
1843 void init_context(context
*ctx
, int_t argc
, char **argv
) {
1844 #define BUILTIN_FUNCTION(name) ctx->store(#name, &builtin_function_##name);
1845 LIST_BUILTIN_FUNCTIONS(BUILTIN_FUNCTION
)
1846 #undef BUILTIN_FUNCTION
1848 #define BUILTIN_CLASS(name) ctx->store(#name, &builtin_class_##name);
1849 LIST_BUILTIN_CLASSES(BUILTIN_CLASS
)
1850 #undef BUILTIN_CLASS
1852 ctx
->store("__name__", new(allocator
) string_const("__main__"));
1853 list
*plist
= new(allocator
) list();
1854 for (int_t a
= 0; a
< argc
; a
++)
1855 plist
->append(new(allocator
) string_const(argv
[a
]));
1856 ctx
->store("__args__", plist
);
1859 void collect_garbage(context
*ctx
, node
*ret_val
) {
1860 static int gc_tick
= 0;
1861 if (++gc_tick
> 128) {
1864 allocator
->mark_dead();
1866 ctx
->mark_live(ret_val
!= NULL
);
1869 ret_val
->mark_live();