Download source/icl/interpreter.py from invariant-computing-lab/icl-native-r5-opcode: direct link, hf CLI and curl.
- Browser
- Download file 4.13 kB
-
https://huggingface.co/invariant-computing-lab/icl-native-r5-opcode/resolve/main/source/icl/interpreter.py
- Command line
-
hf download hf://invariant-computing-lab/icl-native-r5-opcode/source/icl/interpreter.py
-
curl -L -o interpreter.py https://huggingface.co/invariant-computing-lab/icl-native-r5-opcode/resolve/main/source/icl/interpreter.py
4.13 kB
| """Independent recursive tree evaluator: no bytecode compiler or VM calls.""" | |
| from .runtime import ICLError,RuntimeContext,checked_binary,checked_unary,builtin,BUILTINS,digest | |
| from .checker import validate_value | |
| class Returned(Exception): | |
| def __init__(self,value):self.value=value | |
| class Scope: | |
| def __init__(self,parent=None):self.parent=parent;self.values={} | |
| def get(self,name): | |
| if name in self.values:return self.values[name] | |
| if self.parent is not None:return self.parent.get(name) | |
| raise ICLError('NAME','undefined '+name) | |
| def set(self,name,val): | |
| if name in self.values:self.values[name]=val | |
| elif self.parent is not None:self.parent.set(name,val) | |
| else:raise ICLError('NAME','undefined assignment '+name) | |
| def execute_tree(program,entry='main',args=None,limits=None,policy=None): | |
| ctx=RuntimeContext(limits,policy);fs={f['name']:f for f in program['functions']};depth=0 | |
| def ex(x,scope): | |
| chain=[];cur=scope | |
| while cur is not None:chain.append(cur.values);cur=cur.parent | |
| ctx.step('tree.'+x['kind'],inputs={'scope':chain,'prng':ctx.prng}) | |
| event=ctx.trace[-1] | |
| try: | |
| value=_ex(x,scope);event['output_hash']=digest(value);event['state_ref']=event['output_hash'];return value | |
| except ICLError as error:event['error_code']=error.code;raise | |
| def _ex(x,scope): | |
| k=x['kind'] | |
| if k=='literal':return x['value'] | |
| if k=='var':return scope.get(x['name']) | |
| if k=='unary':return checked_unary(x['op'],ex(x['expr'],scope)) | |
| if k=='binary': | |
| a=ex(x['left'],scope) | |
| if x['op']=='&&' and a is False:return False | |
| if x['op']=='||' and a is True:return True | |
| return ctx.check_value(checked_binary(x['op'],a,ex(x['right'],scope))) | |
| if k=='call': | |
| aa=[ex(v,scope) for v in x['args']] | |
| return ctx.check_value(builtin(x['name'],aa,ctx) if x['name'] in BUILTINS else call(x['name'],aa)) | |
| if k in ('list','tuple'):return ctx.check_value([ex(v,scope) for v in x['items']]) | |
| if k=='record':return ctx.check_value({n:ex(x['fields'][n],scope) for n in sorted(x['fields'])}) | |
| if k=='index': | |
| a=ex(x['target'],scope);i=ex(x['index'],scope) | |
| if i<0 or i>=len(a):raise ICLError('BOUNDS','index out of bounds') | |
| return a[i] | |
| if k=='field':return ex(x['target'],scope)[x['name']] | |
| raise ICLError('UNSUPPORTED_OP',k) | |
| def block(ss,parent): | |
| scope=Scope(parent) | |
| for s in ss: | |
| k=s['kind'];ctx.step('tree.'+k) | |
| if k=='let':scope.values[s['name']]=ex(s['expr'],scope) | |
| elif k=='assign':scope.set(s['name'],ex(s['expr'],scope)) | |
| elif k=='return':raise Returned(ex(s['expr'],scope)) | |
| elif k=='expr':ex(s['expr'],scope) | |
| elif k=='if':block(s['then'] if ex(s['cond'],scope) else s['else'],scope) | |
| elif k=='while': | |
| count=0 | |
| while ex(s['cond'],scope): | |
| if count>=s['limit']:raise ICLError('LOOP_LIMIT','declared iteration bound exceeded') | |
| count+=1;block(s['body'],scope) | |
| else:raise ICLError('UNSUPPORTED_OP',k) | |
| def call(name,aa): | |
| nonlocal depth | |
| if name not in fs:raise ICLError('NAME','entry/function missing '+name) | |
| f=fs[name] | |
| if len(aa)!=len(f['params']):raise ICLError('TYPE','function argument count') | |
| depth+=1 | |
| if depth>ctx.limits['max_stack']:raise ICLError('STACK_LIMIT','call stack budget') | |
| env=Scope() | |
| for (n,t),v in zip(f['params'],aa):validate_value(v,t,ctx);env.values[n]=v | |
| try:block(f['body'],env) | |
| except Returned as r:validate_value(r.value,f['return_type'],ctx);return r.value | |
| finally:depth-=1 | |
| raise ICLError('RETURN','function reached end') | |
| try:value=call(entry,args or []) | |
| except RecursionError:raise ICLError('STACK_LIMIT','host recursion boundary reached') | |
| ctx.check_value(value) | |
| return {'value':value,'trace':ctx.trace,'effects':ctx.effects,'steps':ctx.steps} | |