Merge branch 'master' of https://github.com/kanaka/mal
[jackhill/mal.git] / php / types.php
CommitLineData
31690700
JM
1<?php
2
31690700 3
ea81a808
JM
4// Errors/Exceptions
5class Error extends Exception {
6 public $obj = null;
7 public function __construct($obj) {
8 parent::__construct("Mal Error", 0, null);
9 $this->obj = $obj;
10 }
31690700
JM
11}
12
31690700 13
ea81a808 14// General functions
31690700 15
ea81a808 16function _equal_Q($a, $b) {
31690700
JM
17 $ota = gettype($a) === "object" ? get_class($a) : gettype($a);
18 $otb = gettype($b) === "object" ? get_class($b) : gettype($b);
ea81a808 19 if (!($ota === $otb or (_sequential_Q($a) and _sequential_Q($b)))) {
31690700 20 return false;
ea81a808 21 } elseif (_symbol_Q($a)) {
31690700
JM
22 #print "ota: $ota, otb: $otb\n";
23 return $a->value === $b->value;
ea81a808 24 } elseif (_list_Q($a) or _vector_Q($a)) {
31690700
JM
25 if ($a->count() !== $b->count()) { return false; }
26 for ($i=0; $i<$a->count(); $i++) {
ea81a808 27 if (!_equal_Q($a[$i], $b[$i])) { return false; }
31690700
JM
28 }
29 return true;
30 } else {
31 return $a === $b;
32 }
33}
34
ea81a808 35function _sequential_Q($seq) { return _list_Q($seq) or _vector_Q($seq); }
31690700
JM
36
37
ea81a808
JM
38// Scalars
39function _nil_Q($obj) { return $obj === NULL; }
40function _true_Q($obj) { return $obj === true; }
41function _false_Q($obj) { return $obj === false; }
42function _string_Q($obj) { return is_string($obj); }
43
44
45// Symbols
31690700
JM
46class SymbolClass {
47 public $value = NULL;
48 public $meta = NULL;
49 public function __construct($value) {
50 $this->value = $value;
51 }
52}
ea81a808
JM
53function _symbol($name) { return new SymbolClass($name); }
54function _symbol_Q($obj) { return ($obj instanceof SymbolClass); }
31690700 55
b8ee29b2
JM
56// Keywords
57function _keyword($name) { return chr(0x7f).$name; }
58function _keyword_Q($obj) {
59 return is_string($obj) && strpos($obj, chr(0x7f)) === 0;
60}
61
62
31690700
JM
63
64// Functions
65class FunctionClass {
66 public $func = NULL;
67 public $type = 'native'; // 'native' or 'platform'
68 public $meta = NULL;
a34b0200
JM
69 public $ast = NULL;
70 public $env = NULL;
71 public $params = NULL;
31690700 72 public $ismacro = False;
a34b0200
JM
73 public function __construct($func, $type,
74 $ast, $env, $params, $ismacro=False) {
31690700
JM
75 $this->func = $func;
76 $this->type = $type;
a34b0200
JM
77 $this->ast = $ast;
78 #print_r($ast);
79 $this->env = $env;
80 $this->params = $params;
31690700
JM
81 $this->ismacro = $ismacro;
82 }
83 public function __invoke() {
84 $args = func_get_args();
85 if ($this->type === 'native') {
a34b0200
JM
86 $fn_env = new Env($this->env,
87 $this->params, $args);
31690700 88 $evalf = $this->func;
a34b0200 89 return $evalf($this->ast, $fn_env);
31690700
JM
90 } else {
91 return call_user_func_array($this->func, $args);
92 }
93 }
a34b0200
JM
94 public function gen_env($args) {
95 return new Env($this->env, $this->params, $args);
96 }
31690700
JM
97 public function apply($args) {
98 return call_user_func_array(array(&$this, '__invoke'),$args);
99 }
100}
101
a34b0200
JM
102function _function($func, $type='platform',
103 $ast=NULL, $env=NULL, $params=NULL, $ismacro=False) {
104 return new FunctionClass($func, $type, $ast, $env, $params, $ismacro);
31690700 105}
ea81a808 106function _function_Q($obj) { return $obj instanceof FunctionClass; }
31690700 107
31690700
JM
108
109// Parent class of list, vector, hash-map
110// http://www.php.net/manual/en/class.arrayobject.php
111class SeqClass extends ArrayObject {
112 public function slice($start, $length=NULL) {
113 $sc = new $this();
114 if ($start >= count($this)) {
115 $arr = array();
116 } else {
117 $arr = array_slice($this->getArrayCopy(), $start, $length);
118 }
119 $sc->exchangeArray($arr);
120 return $sc;
121 }
122}
123
124
ea81a808
JM
125// Lists
126class ListClass extends SeqClass {
127 public $meta = NULL;
128}
129
130function _list() {
131 $v = new ListClass();
132 $v->exchangeArray(func_get_args());
133 return $v;
134}
135function _list_Q($obj) { return $obj instanceof ListClass; }
136
137
138// Vectors
139class VectorClass extends SeqClass {
140 public $meta = NULL;
141}
142
143function _vector() {
144 $v = new VectorClass();
145 $v->exchangeArray(func_get_args());
146 return $v;
147}
148function _vector_Q($obj) { return $obj instanceof VectorClass; }
149
150
31690700
JM
151// Hash Maps
152class HashMapClass extends ArrayObject {
153 public $meta = NULL;
154}
155
ea81a808 156function _hash_map() {
31690700
JM
157 $args = func_get_args();
158 if (count($args) % 2 === 1) {
159 throw new Exception("Odd number of hash map arguments");
160 }
161 $hm = new HashMapClass();
162 array_unshift($args, $hm);
ea81a808 163 return call_user_func_array('_assoc_BANG', $args);
31690700 164}
ea81a808 165function _hash_map_Q($obj) { return $obj instanceof HashMapClass; }
31690700 166
ea81a808 167function _assoc_BANG($hm) {
31690700
JM
168 $args = func_get_args();
169 if (count($args) % 2 !== 1) {
170 throw new Exception("Odd number of assoc arguments");
171 }
172 for ($i=1; $i<count($args); $i+=2) {
173 $ktoken = $args[$i];
174 $vtoken = $args[$i+1];
175 // TODO: support more than string keys
176 if (gettype($ktoken) !== "string") {
177 throw new Exception("expected hash-map key string, got: " . gettype($ktoken));
178 }
179 $hm[$ktoken] = $vtoken;
180 }
181 return $hm;
182}
183
ea81a808 184function _dissoc_BANG($hm) {
31690700
JM
185 $args = func_get_args();
186 for ($i=1; $i<count($args); $i++) {
187 $ktoken = $args[$i];
b079f510
JM
188 if ($hm && $hm->offsetExists($ktoken)) {
189 unset($hm[$ktoken]);
190 }
31690700
JM
191 }
192 return $hm;
193}
194
31690700
JM
195
196// Atoms
31690700
JM
197class Atom {
198 public $value = NULL;
199 public $meta = NULL;
200 public function __construct($value) {
201 $this->value = $value;
202 }
203}
ea81a808
JM
204function _atom($val) { return new Atom($val); }
205function _atom_Q($atm) { return $atm instanceof Atom; }
31690700
JM
206
207?>