Search code examples
iolanguage

Io language different behavior between interpreter and file execution


I am trying to create a new operator in the Io language, but I've noticed different behavior when I check my work with an interpreter versus file execution:

## Executing nand.io
##########################
OperatorTable addOperator("nand", 10)
true nand := method(bool, if(bool, false, true))
false nand := method(bool, true)

true nand false println        # => false
true nand true println         # => true
false nand false println       # => false
false nand true println        # => true

# Why does this print 'true' (it should be 'false')?
(true nand true) println      # => true

# I noticed that the argument to nand is always printed
true nand "not" println        # => not
true nand "what" println       # => what
false nand "I" println         # => I
false nand "expected" println  # => expected

# Another sanity check. I thought this might have to do with println behaving
# oddly, but this conditional really does return true
if(true nand true, "This should not print" println, "This should print" println)
# => This should not print

# More unexpected behavior
false nand := method(arg, "foo")
false nand "bar" println       # => "bar"

true nand := method(arg, "foo")
true nand "bar" println        # => "bar"

false nand := "Why is this not returned?"
false nand "aaaaahhhh" println # => "aaaaahhhh"



## Ran in the io interpreter
###############################
OperatorTable addOperator("nand", 10)
true nand := method(bool, if(bool, false, true))
false nand := method(bool, true)

# Same as file execution when sent to println
true nand false println   # => false
true nand true println    # => true
false nand false println  # => false
false nand true println   # => true

# It acually does what's expected here
true nand false           # => true
true nand true            # => false    -- It works here!!!
false nand false          # => true
false nand true           # => true

if(true nand true, "This should not print" println, "This should print" println)
# => This should print

Maybe this has to do compilation vs interpretation? Is this actually expected behavior and maybe I'm missing something fundamental about the language (I only started learning Io today)?


Solution

  • Ok so this has to do with the way the VM parses operators. The first pass of the file will go through and rewrite any operators it knows about already, rewriting the messages in relation to the number supplied as precedence. The second pass will then execute that modified message tree. Because of this, when you add a new operator to the operator table in a file that you later pass through the VM, your new operator will only be available to any files or modules you load after that. For the life of that message tree that was produced from that file, your operator doesn't exist.

    Basically the rule of thumb here is to maintain a separate operators.io file, and your main io file separate; then ensure operators.io gets loaded before main.io, and you'll be all set.

    The reason the CLI doesn't have this problem is because it evaluates messages one by one. That is to say, the next message you type in will have the new operator st