Clean up attr resolution.

This commit is contained in:
Russ Olsen 2020-04-23 09:10:27 -04:00
parent 965f78f142
commit a4e2a1997a
5 changed files with 164 additions and 77 deletions

View file

@ -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 ;

View file

@ -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")

View file

@ -50,6 +50,7 @@ def repl(f):
line = input(p)
except KeyboardInterrupt:
print("<<interrupt>>")
f.stack.reset()
line = ''
except EOFError:
break

View file

@ -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

View file

@ -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,10 +83,35 @@ 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)
return i + 1
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))
@ -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()