def register_ctor(name: Type_name, op: Operation, input_sig: List["StackObject"]) -> None: # Ctors only have TypeSignatures that return their own Type. # Register the ctor in the Global dictionary. op.sig = TypeSignature(input_sig, [StackObject(stype=Type(name))]) # Type.add_op(op) # Append this ctor to our list of valid ctors. op_map = Type.ctors.get(name, None) assert op_map is not None, ( "No ctor map for type %s found.\n\tCtors exist for the following types: %s." % (name, Type.ctors.keys())) op_map.append((input_sig, op))
def test_op_with_type_multi_output_signature(self) -> None: stack = Stack() cont = Continuation(stack) make_word_context("test", lambda cont: 42, [], [TTest, TParm1]) print_words() op, found = Type.op("test", cont) #, "Test") assert found assert op.sig == TypeSignature( [], [StackObject(stype=TTest), StackObject(stype=TParm1)]) op( cont ) # Do this so the lambda doesn't get counted as a missed branch in our code coverage. op, found = Type.op("not found", cont) assert not found
def find_op(name: Op_name, cont: AF_Continuation, type_name: Type_name) -> Tuple[Operation, bool]: type_def: TypeDefinition = Type.types[ type_name] # (type_name,Type.types["Any"]) cont.log.debug("Searching for op:'%s' in type: '%s'." % (name, type_name)) assert type_def is not None, "No type '%s' found. We have: %s" % ( type, Type.types.keys()) name_found = False sigs_found: List[TypeSignature] = [] if type_def: op_list = type_def.ops_list cont.log.debug("\top_list = %s" % [op for op in op_list]) for op in op_list: if op.name == name: name_found = True sigs_found.append(op.sig) # Now try to match the input stack... try: if op.check_stack_effect( cont.stack ): # TODO - are we doing the right thing with this return types? cont.log.debug("Found! Returning %s, %s, %s" % (op, op.sig, True)) return op, True except SigValueTypeMismatchException: # We found the name but not the right value/type sig. Keep looking. pass # Not found. if name_found: # Is this what we want to do? # This will happen if names match but stacks don't. cont.log.debug( "Continuation (stack = %s) doesn't match Op '%s' with available signatures: %s." % (cont.stack, name, [s.stack_in for s in sigs_found])) raise Exception( "Continuation (stack = %s) doesn't match Op '%s' with available signatures: %s." % (cont.stack, name, [s.stack_in for s in sigs_found])) cont.log.debug("Not found!") # Default operation is to treat the symbol as an Atom and put it on the stack. return Operation("make_atom", make_atom, sig=TypeSignature([], [StackObject(stype=TAtom)])), False
def test_op_dup(self) -> None: @dataclass class DupTest: val: str self.c.stack.push(StackObject(value=DupTest("Something"), stype=TAtom)) op_dup(self.c) op_dup(self.c) item1 = self.c.stack.pop() self.c.stack.tos().value.val = "SomethingElse" assert item1.value.val == "Something" item2 = self.c.stack.pop() assert item2.value.val == "SomethingElse" assert item1 != item2 item3 = self.c.stack.pop() assert item3.value.val == "Something" assert item2 != item3 assert item1 == item3
def test_curry_match_and_execute(self) -> None: words = [ Operation("test", op_gen(StackObject(stype=TInt, value=99), 1), sig=TypeSignature([self.zero_pattern], [self.int_pattern])) ] curry, sig = match_and_execute_compiled_word(self.cont, words) self.cont.stack.push(StackObject(stype=TInt, value=0)) curry(self.cont) assert self.cont.stack.pop().value == 99 self.cont.stack.push(StackObject(stype=TInt, value=1)) with self.assertRaises(Exception) as x: curry(self.cont) words.append( Operation("test", op_gen(StackObject(stype=TInt, value=101), 1), sig=TypeSignature([self.one_pattern], [self.int_pattern]))) curry(self.cont) assert self.cont.stack.pop().value == 101 words.append( Operation("test", op_gen(StackObject(stype=TInt, value=76), 1), sig=TypeSignature([self.any_pattern], [self.int_pattern]))) self.cont.stack.push(StackObject(stype=TInt, value=0)) self.cont.stack.push(StackObject(stype=TInt, value=42)) curry(self.cont) assert self.cont.stack.pop().value == 76 curry(self.cont) assert self.cont.stack.pop().value == 99
def setUp(self) -> None: self.stack = Stack() self.cont = Continuation(self.stack) self.save_types = deepcopy(Type.types) self.save_ctors = deepcopy(Type.ctors) self.zero_pattern = StackObject(stype=TInt, value=0) self.one_pattern = StackObject(stype=TInt, value=1) self.any_pattern = StackObject(stype=TAny) self.true_pattern = StackObject(stype=TBool, value=True) self.false_pattern = StackObject(stype=TBool, value=False) self.int_pattern = StackObject(stype=TInt) op_debug(self.cont) op_on(self.cont)
def test_op_drop(self) -> None: self.s.push(StackObject(stype=TAtom, value="test")) op_drop(self.c) assert self.c.stack.depth() == 0
def op_equals(c: AF_Continuation) -> None: sobj1 = optionally_infer_type_from_atom(c) # Now we pop off whatever is the ultimate object that's # possibly been inferred. sobj2 = c.stack.pop() c.stack.push(StackObject(value=(sobj1 == sobj2), stype=TBool))
def op_greater_than_or_equal_to(c: AF_Continuation) -> None: sobj1 = optionally_infer_type_from_atom(c) sobj2 = c.stack.pop() c.stack.push(StackObject(value=(sobj2.value >= sobj1.value), stype=TBool))
if stack_object.stype == TAtom: #print ("Got an Atom") if stack_object.value == "True": #print ("Found a True Atom") result.value = True if stack_object.value == "False": #print ("Found a False Atom") result.value = False assert result.value is not None, "%s is not a valid Boolean value." % stack_object.value c.stack.push(result) Type.register_ctor('Bool', Operation('bool', op_bool), [StackObject(stype=TAtom)]) Type.register_ctor('Bool', Operation('bool', op_bool), [StackObject(stype=TBool)]) #Type.register_ctor('Bool',Operation('bool',op_bool),[StackObject(stype=TAny)]) # HACK BDM TODO NASTY! ### TODO : if issue 4 ( https://github.com/ActorForth/ActorForth/issues/4 ) ### is working properly then we shouldn't need this, right? make_word_context('bool', op_bool, [TAtom], [TBool]) make_word_context('bool', op_bool, [TBool], [TBool]) # TODO : issue #17 wait for created gerneralize type infer def optionally_infer_type_from_atom(c: AF_Continuation) -> StackObject: #op_debug(c) #op_on(c)
def make_ratom(c: AF_Continuation) -> None: c.rstack.push(StackObject(value=c.symbol.s_id, stype=TAtom))