mirror of
https://github.com/russolsen/sallyforth
synced 2024-12-25 21:58:18 +01:00
Clean up attr resolution.
This commit is contained in:
parent
965f78f142
commit
a4e2a1997a
5 changed files with 164 additions and 77 deletions
|
@ -1,17 +1,14 @@
|
|||
"List" p
|
||||
|
||||
: [n] (n list -- nth-item)
|
||||
2 ->list \ Make the arg list.
|
||||
<. builtins.list '__getitem__ .> \ Find the getitem method.
|
||||
!! \ Call!
|
||||
;
|
||||
\ Index into the x'th item.
|
||||
: [x] (col key -- value) 1 ->list '__getitem__ .!! ;
|
||||
|
||||
: first (list -- first-item) 0 swap [n] ;
|
||||
: second (list -- second-item) 1 swap [n] ;
|
||||
: third (list -- third-item) 2 swap [n] ;
|
||||
: fourth (list -- fourth-item) 3 swap [n] ;
|
||||
: first (list -- first-item) 0 [x] ;
|
||||
: second (list -- second-item) 1 [x] ;
|
||||
: third (list -- third-item) 2 [x] ;
|
||||
: fourth (list -- fourth-item) 3 [x] ;
|
||||
|
||||
: last (list -- last-item) -1 swap [n] ;
|
||||
: last (list -- last-item) -1 [x] ;
|
||||
|
||||
: slice (start stop -- slice-obj)
|
||||
swap
|
||||
|
@ -22,15 +19,18 @@
|
|||
|
||||
: take (n list -- first-n-items)
|
||||
swap 0 swap slice \ Make the 0..n slice.
|
||||
swap [n] \ Do a[0..n].
|
||||
[x] \ Do a[0..n].
|
||||
;
|
||||
|
||||
: drop (n list -- all-but-first-n-items)
|
||||
swap nil slice \ Make the n..None slice.
|
||||
swap [n]
|
||||
[x]
|
||||
;
|
||||
|
||||
: rest (list -- all-but-first) 1 swap drop ;
|
||||
: rrest (list -- rest-of-rest) rest rest ;
|
||||
: rrrest (list -- all-but-first) rest rest rest ;
|
||||
|
||||
|
||||
|
||||
|
||||
: first (list -- first-item) 1 swap drop ;
|
||||
: ffirst (list -- first-of-first) first first ;
|
||||
: fffirst (list -- fff-irst) first first first ;
|
||||
|
|
|
@ -62,7 +62,7 @@ class Namespace:
|
|||
return self.contents.__iter__()
|
||||
|
||||
def __getitem__(self, key):
|
||||
# print("get item", key, self.contents)
|
||||
#print("get item", key, self.name)
|
||||
if key in self.contents:
|
||||
return self.contents[key]
|
||||
# print("not in local ns")
|
||||
|
|
|
@ -50,6 +50,7 @@ def repl(f):
|
|||
line = input(p)
|
||||
except KeyboardInterrupt:
|
||||
print("<<interrupt>>")
|
||||
f.stack.reset()
|
||||
line = ''
|
||||
except EOFError:
|
||||
break
|
||||
|
|
|
@ -15,11 +15,11 @@
|
|||
'dot '. alias
|
||||
'colon ': alias
|
||||
'semi '; alias
|
||||
'thread '@@ alias
|
||||
'bounded_list '[list] alias
|
||||
'list '->list alias
|
||||
'to_arglist '->arglist alias
|
||||
'list_to_map 'list->map alias
|
||||
'lookup '@@ alias
|
||||
'call '!! alias
|
||||
'add '+ alias
|
||||
'sub '- alias
|
||||
|
@ -59,11 +59,8 @@
|
|||
: [: [ ;
|
||||
: :] ] ->arglist ;
|
||||
|
||||
: => [ ;
|
||||
: >! ] arrow ;
|
||||
|
||||
: <. [ ;
|
||||
: .> ] arrow ;
|
||||
: .> ] thread ;
|
||||
|
||||
: !!0 [] swap call ;
|
||||
|
||||
|
@ -86,6 +83,7 @@
|
|||
|
||||
: -- -1 + ;
|
||||
: ++ 1 + ;
|
||||
: *2 2 * ;
|
||||
: pos? 0 > ;
|
||||
: neg? 0 < ;
|
||||
: zero? 0 = ;
|
||||
|
@ -97,13 +95,10 @@
|
|||
if source else drop then
|
||||
;
|
||||
|
||||
: << [ ;
|
||||
: >>@ ] @@ ;
|
||||
: >>! ] @@ [] swap !! ;
|
||||
: getattr (x 'fieldname -- field) swap 2 ->list builtins.getattr ;
|
||||
: .!! (obj args method-name -- result) tbm getattr !! ;
|
||||
|
||||
"string.sf" source
|
||||
"list.sf" source
|
||||
|
||||
"init.sf" source-if-exists
|
||||
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
from inspect import isfunction, isbuiltin
|
||||
import importlib
|
||||
import os
|
||||
from compiler import Compiler
|
||||
from arglist import Arglist
|
||||
|
||||
|
@ -16,8 +17,11 @@ def const_f(value):
|
|||
def native_function_handler(func):
|
||||
def handle(forth, i):
|
||||
args = forth.stack.pop()
|
||||
#print(f"Native fun, calling {func}({args})")
|
||||
result = func(*args)
|
||||
#print(f'Result: {result}')
|
||||
forth.stack.push(result)
|
||||
#print("pushed result")
|
||||
return i + 1
|
||||
return handle
|
||||
|
||||
|
@ -35,6 +39,11 @@ def import_native_module(forth, m, alias=None, excludes=[]):
|
|||
else:
|
||||
forth.namespace[localname] = const_f(val)
|
||||
|
||||
def w_eval(f, i):
|
||||
token = f.stack.pop()
|
||||
f.execute_token(token)
|
||||
return i+1
|
||||
|
||||
def w_no_op(f, i):
|
||||
return i+1
|
||||
|
||||
|
@ -74,11 +83,36 @@ def w_require(f, i):
|
|||
import_native_module(f, m, name)
|
||||
return i + 1
|
||||
|
||||
def source(f, path):
|
||||
old_source_f = f.namespace.get('*source*', None)
|
||||
old_namespace = f.namespace
|
||||
try:
|
||||
f.execute_file(path)
|
||||
finally:
|
||||
f.namespace['*source*'] = old_source_f
|
||||
f.namespace = old_namespace
|
||||
|
||||
def w_load(f, i):
|
||||
path = f.stack.pop()
|
||||
source(f, path)
|
||||
return i + 1
|
||||
|
||||
def w_source(f, i):
|
||||
path = f.stack.pop()
|
||||
f.execute_file(path)
|
||||
if os.path.isabs(path):
|
||||
source(f, path)
|
||||
return i+1
|
||||
|
||||
relative_dir = os.path.dirname(f.evaluate_token('*source*'))
|
||||
relative_path = f'{relative_dir}/{path}'
|
||||
if os.path.exists(relative_path):
|
||||
source(f, relative_path)
|
||||
return i+1
|
||||
|
||||
source(f, path)
|
||||
return i+1
|
||||
|
||||
|
||||
def execute_f(name, instructions):
|
||||
#print('execute_f:', name, len(instructions))
|
||||
def inner(forth, i, debug=False):
|
||||
|
@ -140,6 +174,43 @@ def w_unique(f, ip): # pushes a uique object.
|
|||
f.stack.push(Unique())
|
||||
return ip+1
|
||||
|
||||
def w_map(f, ip):
|
||||
l = f.stack.pop()
|
||||
word = f.stack.pop()
|
||||
|
||||
word_f = f.namespace.get(word, None)
|
||||
result = []
|
||||
|
||||
for item in l:
|
||||
f.stack.push(item)
|
||||
word_f(f, 0)
|
||||
result.append(f.stack.pop())
|
||||
|
||||
f.stack.push(result)
|
||||
return ip+1
|
||||
|
||||
def w_reduce(f, ip):
|
||||
l = f.stack.pop()
|
||||
word = f.stack.pop()
|
||||
|
||||
word_f = f.namespace.get(word, None)
|
||||
|
||||
if len(l) <= 0:
|
||||
f.stack.push(None)
|
||||
elif len(l) == 1:
|
||||
f.stack.push(l[0])
|
||||
else:
|
||||
result = l[0]
|
||||
l = l[1::-1]
|
||||
for item in l:
|
||||
f.stack.push(result)
|
||||
f.stack.push(item)
|
||||
word_f(f, 0)
|
||||
result = f.stack.pop()
|
||||
f.stack.push(result)
|
||||
|
||||
return ip+1
|
||||
|
||||
def w_bounded_list(f, ip):
|
||||
"""Create a list from delimted values on the stack.
|
||||
[list]
|
||||
|
@ -168,34 +239,17 @@ def w_list(f, ip): # ->list
|
|||
f.stack.push(l)
|
||||
return ip+1
|
||||
|
||||
def qqw_lookup(f, i): # @@
|
||||
l = f.stack.pop()
|
||||
value = l[0]
|
||||
for field in l[1::]:
|
||||
value = getattr(value, field)
|
||||
f.stack.push(value)
|
||||
return i+1
|
||||
|
||||
def w_lookup(f, i): # ->
|
||||
value = f.stack.pop()
|
||||
fields = f.stack.pop()
|
||||
print(f'value {value} fields {fields}')
|
||||
|
||||
if not isinstance(fields, list):
|
||||
fields = [fields]
|
||||
|
||||
for field in fields:
|
||||
print(f'value {value} field {field}')
|
||||
if isinstance(field, str) and hasattr(value, field):
|
||||
print("->getattr")
|
||||
value = getattr(value, field)
|
||||
def w_thread(f, i): # @@
|
||||
contents = f.stack.pop()
|
||||
result = contents[0]
|
||||
for field in contents[1::]:
|
||||
if isinstance(field, str) and hasattr(result, field):
|
||||
result = getattr(result, field) # result.field
|
||||
elif isinstance(field, Arglist):
|
||||
print("->arglist")
|
||||
value = value(*field)
|
||||
result = result(*field) # result(*field)
|
||||
else:
|
||||
print("index")
|
||||
value = value[field]
|
||||
f.stack.push(value)
|
||||
result = result[field] # result[field]
|
||||
f.stack.push(result)
|
||||
return i+1
|
||||
|
||||
|
||||
|
@ -259,23 +313,6 @@ def w_getattribute(f, i):
|
|||
f.stack.push(result)
|
||||
return i+1
|
||||
|
||||
def w_arrow(f, i): # ->
|
||||
contents = f.stack.pop()
|
||||
result = contents[0]
|
||||
for field in contents[1::]:
|
||||
print(f'result {result} field {field}')
|
||||
if isinstance(field, str) and hasattr(result, field):
|
||||
print("->getattr")
|
||||
result = getattr(result, field)
|
||||
elif isinstance(field, Arglist):
|
||||
print("->arglist")
|
||||
result = result(*field)
|
||||
else:
|
||||
print("index")
|
||||
result = result[field]
|
||||
f.stack.push(result)
|
||||
return i+1
|
||||
|
||||
def w_def(f, i):
|
||||
value = f.stack.pop()
|
||||
name = f.stack.pop()
|
||||
|
@ -351,6 +388,60 @@ def w_dup(f, i):
|
|||
f.stack.push(x)
|
||||
return i+1
|
||||
|
||||
def w_tmb(f, i): # A noop
|
||||
# t = f.stack.pop()
|
||||
# m = f.stack.pop()
|
||||
# b = f.stack.pop()
|
||||
# f.stack.push(b)
|
||||
# f.stack.push(m)
|
||||
# f.stack.push(t)
|
||||
return i+1
|
||||
|
||||
def w_tbm(f, i):
|
||||
t = f.stack.pop()
|
||||
m = f.stack.pop()
|
||||
b = f.stack.pop()
|
||||
f.stack.push(m)
|
||||
f.stack.push(b)
|
||||
f.stack.push(t)
|
||||
return i+1
|
||||
|
||||
def w_bmt(f, i):
|
||||
t = f.stack.pop()
|
||||
m = f.stack.pop()
|
||||
b = f.stack.pop()
|
||||
f.stack.push(t)
|
||||
f.stack.push(m)
|
||||
f.stack.push(b)
|
||||
return i+1
|
||||
|
||||
def w_btm(f, i):
|
||||
t = f.stack.pop()
|
||||
m = f.stack.pop()
|
||||
b = f.stack.pop()
|
||||
f.stack.push(m)
|
||||
f.stack.push(t)
|
||||
f.stack.push(b)
|
||||
return i+1
|
||||
|
||||
def w_mtb(f, i):
|
||||
t = f.stack.pop()
|
||||
m = f.stack.pop()
|
||||
b = f.stack.pop()
|
||||
f.stack.push(b)
|
||||
f.stack.push(t)
|
||||
f.stack.push(m)
|
||||
return i+1
|
||||
|
||||
def w_mbt(f, i):
|
||||
t = f.stack.pop()
|
||||
m = f.stack.pop()
|
||||
b = f.stack.pop()
|
||||
f.stack.push(t)
|
||||
f.stack.push(b)
|
||||
f.stack.push(m)
|
||||
return i+1
|
||||
|
||||
def w_rot(f, i):
|
||||
c = f.stack.pop()
|
||||
b = f.stack.pop()
|
||||
|
|
Loading…
Reference in a new issue