Discussion:
curlyBrackets & squareBrackets
sunwinson
2012-11-12 14:10:05 UTC
Permalink
I was confused about how "curlyBrackets" or "squareBrackets" are over rided by runtime.

[Example]
I saw some wonderful example about redefining curlyBrackets or squareBrackets, to create graceful DSL to handle the next txt file:
{
"Blair, Black": 10,
"John, Kelly": 11
}

Redefining "curlyBrackets" can operate the item one by by as a map.

[My Research]
I searched:
1. all slotNames of "Object" for "curlyBrackets", none was found.
2. source code of Io language, only find one instance in Lexer, which returns "curlyBrackets" as the name of IDENTIFIER token and finally become the name of IoObject/IoObjectData. The weird thing is, it seems no one is using IoObject name or IDENTIFIER in parser. May I miss anything in source code?

[My Guess]
1. "curlyBrackets" should be some one's secret slot name, but I didn't find in reference nor Object/Lobby.
2. "curlyBrackets" is specially proceed in parser, to check "if anyone implement that name, then use the specified method object".

Could anyone can help me to understand how this "curlyBrackets" works from complier perspective? Thanks a lot!
Jeremy Tregunna
2012-11-13 20:41:30 UTC
Permalink
Alright, so "curlyBrackets", "squareBrackets" and "" are all treated specially. They correspond to {}, [] and ().

They are processed specially because they capture infix expressions. That is to say, the expression itself is stuck between two known tokens.

I'll provide an implementation of list() using all three (tl;dr, it's the same code for all three methods)

curlyBrackets := method(call evalArgs)
squareBrackets := method(call evalArgs)
setSlot("", method(call evalArgs))

Now we can do: {1, 2, 3} or [1, 2, 3] or (1, 2, 3) /* so long as the latter is preceded by a space */

and things just magically work as you'd expect. That method is called, and since "call evalArgs" iterates over the messages supplied as arguments, evaluating them in the sending context.

The "curlyBrackets" and "squareBrackets" methods are not defined by default, they are permitted for user code, but the core language doesn't define them. "" on the other hand, is defined by the system, and it's just defined as:

setSlot("", method(call evalArgAt(0)))

I hope this clears up how this works.

Regards,

Jeremy Tregunna
Post by sunwinson
I was confused about how "curlyBrackets" or "squareBrackets" are over rided by runtime.
[Example]
{
"Blair, Black": 10,
"John, Kelly": 11
}
Redefining "curlyBrackets" can operate the item one by by as a map.
[My Research]
1. all slotNames of "Object" for "curlyBrackets", none was found.
2. source code of Io language, only find one instance in Lexer, which returns "curlyBrackets" as the name of IDENTIFIER token and finally become the name of IoObject/IoObjectData. The weird thing is, it seems no one is using IoObject name or IDENTIFIER in parser. May I miss anything in source code?
[My Guess]
1. "curlyBrackets" should be some one's secret slot name, but I didn't find in reference nor Object/Lobby.
2. "curlyBrackets" is specially proceed in parser, to check "if anyone implement that name, then use the specified method object".
Could anyone can help me to understand how this "curlyBrackets" works from complier perspective? Thanks a lot!
Jacob Peck
2012-11-13 20:45:47 UTC
Permalink
From the source code, it's pretty clear here:

https://github.com/stevedekorte/io/blob/master/libs/iovm/source/IoLexer.c#L558-563

That is, [] and {} are just replaced with the message "squareBrackets"
and "curlyBrackets", and from then on they're passed along just like any
other message. It's in the lexer, before the parser even gets a hold of
them.

-->Jake
Post by Jeremy Tregunna
Alright, so "curlyBrackets", "squareBrackets" and "" are all treated
specially. They correspond to {}, [] and ().
They are processed specially because they capture infix expressions.
That is to say, the expression itself is stuck between two known tokens.
I'll provide an implementation of list() using all three (tl;dr, it's
the same code for all three methods)
curlyBrackets := method(call evalArgs)
squareBrackets := method(call evalArgs)
setSlot("", method(call evalArgs))
Now we can do: {1, 2, 3} or [1, 2, 3] or (1, 2, 3) /* so long as the
latter is preceded by a space */
and things just magically work as you'd expect. That method is called,
and since "call evalArgs" iterates over the messages supplied as
arguments, evaluating them in the sending context.
The "curlyBrackets" and "squareBrackets" methods are not defined by
default, they are permitted for user code, but the core language
doesn't define them. "" on the other hand, is defined by the system,
setSlot("", method(call evalArgAt(0)))
I hope this clears up how this works.
Regards,
Jeremy Tregunna
Post by sunwinson
I was confused about how "curlyBrackets" or "squareBrackets" are over rided by runtime.
[Example]
I saw some wonderful example about redefining curlyBrackets or
{
"Blair, Black": 10,
"John, Kelly": 11
}
Redefining "curlyBrackets" can operate the item one by by as a map.
[My Research]
1. all slotNames of "Object" for "curlyBrackets", none was found.
2. source code of Io language, only find one instance in Lexer, which
returns "curlyBrackets" as the name of IDENTIFIER token and finally
become the name of IoObject/IoObjectData. The weird thing is, it
seems no one is using IoObject name or IDENTIFIER in parser. May I
miss anything in source code?
[My Guess]
1. "curlyBrackets" should be some one's secret slot name, but I
didn't find in reference nor Object/Lobby.
2. "curlyBrackets" is specially proceed in parser, to check "if
anyone implement that name, then use the specified method object".
Could anyone can help me to understand how this "curlyBrackets" works
from complier perspective? Thanks a lot!
sunwinson
2012-11-18 16:33:29 UTC
Permalink
Jake (and all interested),

Yes, I found the code you mentioned.

This part is only effective on Lex, which are creating for tokens (Type := IDENTIFIER).

Tokens are output of IoLexer_lex, keepinging in IoState.tokenStream.

Token name will be copied to DATA(IoMessage)->name, and arguments will be attached to the same IoMessage too.

In my head, the next sample code,
[Io]
Table area( x, y, angle)

will be translated into parser tree as:

[parser 1]
Table{IoObject} -> area(IoMessage) -> ""(IoMessage) -> x, y, angle (IoList)

or

[parser 2]
Table{IoObject} -> area(IoMessage) -> x, y, angle (IoList)

If [parser 1] is correct, the overrided "" will replace the original CFunction, then it works well.

If [parser 2] is correct, I have no idea how "" is replaced internally when user define their own "" method.

[My Questions]
In my intuitive sense, I think [parser 2] is the correct one in Io Engine. For this assumption, how "" method replace original CFunction in Paser? There should be some code to search "" matching, I think, while, I didn't find~~~.

Can anyone enlight me, how this replacement of "Brackets" works, how the Engine find the overrided method and execute it?

I want to understand more to implement some feature to replace seperator "," in the future.

Many thanks!

Winson
Post by Jacob Peck
https://github.com/stevedekorte/io/blob/master/libs/iovm/source/IoLexer.c#L558-563
That is, [] and {} are just replaced with the message "squareBrackets"
and "curlyBrackets", and from then on they're passed along just like any
other message. It's in the lexer, before the parser even gets a hold of
them.
-->Jake
Post by Jeremy Tregunna
Alright, so "curlyBrackets", "squareBrackets" and "" are all treated
specially. They correspond to {}, [] and ().
They are processed specially because they capture infix expressions.
That is to say, the expression itself is stuck between two known tokens.
I'll provide an implementation of list() using all three (tl;dr, it's
the same code for all three methods)
curlyBrackets := method(call evalArgs)
squareBrackets := method(call evalArgs)
setSlot("", method(call evalArgs))
Now we can do: {1, 2, 3} or [1, 2, 3] or (1, 2, 3) /* so long as the
latter is preceded by a space */
and things just magically work as you'd expect. That method is called,
and since "call evalArgs" iterates over the messages supplied as
arguments, evaluating them in the sending context.
The "curlyBrackets" and "squareBrackets" methods are not defined by
default, they are permitted for user code, but the core language
doesn't define them. "" on the other hand, is defined by the system,
setSlot("", method(call evalArgAt(0)))
I hope this clears up how this works.
Regards,
Jeremy Tregunna
Post by sunwinson
I was confused about how "curlyBrackets" or "squareBrackets" are over
rided by runtime.
[Example]
I saw some wonderful example about redefining curlyBrackets or
{
"Blair, Black": 10,
"John, Kelly": 11
}
Redefining "curlyBrackets" can operate the item one by by as a map.
[My Research]
1. all slotNames of "Object" for "curlyBrackets", none was found.
2. source code of Io language, only find one instance in Lexer, which
returns "curlyBrackets" as the name of IDENTIFIER token and finally
become the name of IoObject/IoObjectData. The weird thing is, it
seems no one is using IoObject name or IDENTIFIER in parser. May I
miss anything in source code?
[My Guess]
1. "curlyBrackets" should be some one's secret slot name, but I
didn't find in reference nor Object/Lobby.
2. "curlyBrackets" is specially proceed in parser, to check "if
anyone implement that name, then use the specified method object".
Could anyone can help me to understand how this "curlyBrackets" works
from complier perspective? Thanks a lot!
Steve Dekorte
2012-11-18 17:13:36 UTC
Permalink
Post by sunwinson
[Io]
Table area( x, y, angle)
[parser 1]
Table{IoObject} -> area(IoMessage) -> ""(IoMessage) -> x, y, angle (IoList)
or
[parser 2]
Table{IoObject} -> area(IoMessage) -> x, y, angle (IoList)
Hi Winson,

All tokens are translated to IoMessages:

Table(IoMessage) -next-> area(IoMessage) -args-> [x (IoMessage), y (IoMessage), angle (IoMessage)]

The "" message is only used where there is no message name before the ().

Steve
Steve Dekorte
2012-11-18 20:19:52 UTC
Permalink
Post by sunwinson
Can anyone enlight me, how this replacement of "Brackets" works, how the Engine find the overrided method and execute it?
I want to understand more to implement some feature to replace seperator "," in the future.
You don't "override" it so much as define it. The lexer just converts {} to curlyBrackets. If it's not defined and the code is executed, you'll get a "Object does not respond to 'curlyBrackets'" exception.

Steve
daipeng
2012-11-20 11:03:54 UTC
Permalink
Post by sunwinson
Post by sunwinson
Can anyone enlight me, how this replacement of "Brackets" works, how
the Engine find the overrided method and execute it?
Post by sunwinson
I want to understand more to implement some feature to replace
seperator "," in the future.
You don't "override" it so much as define it. The lexer just converts
{} to curlyBrackets. If it's not defined and the code is executed,
you'll get a "Object does not respond to 'curlyBrackets'" exception.
Steve
hi to all:
new to Io, But really feel attracted by the simple language syntax.
But what confuse me so long is I can't even find a sample project in
both googleCode or github(indeed there have some in the github, but
seems far away from what I have execped).
So can anyone explain me which place to use io . or some sample
project.Thanks at first.

daipeng

sunwinson
2012-11-18 16:15:03 UTC
Permalink
Hi, Jeremy,

Thanks for your detailed explaination!

I understand how user should use "brackets" according to "Io language" sample code.

What I am not sure is, I collected both Lobby/Block/Object slotNames, and find none "Brackets" slots defined, so that we can "override" these slots.

Regards,

Winson
Post by Jeremy Tregunna
Alright, so "curlyBrackets", "squareBrackets" and "" are all treated specially. They correspond to {}, [] and ().
They are processed specially because they capture infix expressions. That is to say, the expression itself is stuck between two known tokens.
I'll provide an implementation of list() using all three (tl;dr, it's the same code for all three methods)
curlyBrackets := method(call evalArgs)
squareBrackets := method(call evalArgs)
setSlot("", method(call evalArgs))
Now we can do: {1, 2, 3} or [1, 2, 3] or (1, 2, 3) /* so long as the latter is preceded by a space */
and things just magically work as you'd expect. That method is called, and since "call evalArgs" iterates over the messages supplied as arguments, evaluating them in the sending context.
setSlot("", method(call evalArgAt(0)))
I hope this clears up how this works.
Regards,
Jeremy Tregunna
Post by sunwinson
I was confused about how "curlyBrackets" or "squareBrackets" are over rided by runtime.
[Example]
{
"Blair, Black": 10,
"John, Kelly": 11
}
Redefining "curlyBrackets" can operate the item one by by as a map.
[My Research]
1. all slotNames of "Object" for "curlyBrackets", none was found.
2. source code of Io language, only find one instance in Lexer, which returns "curlyBrackets" as the name of IDENTIFIER token and finally become the name of IoObject/IoObjectData. The weird thing is, it seems no one is using IoObject name or IDENTIFIER in parser. May I miss anything in source code?
[My Guess]
1. "curlyBrackets" should be some one's secret slot name, but I didn't find in reference nor Object/Lobby.
2. "curlyBrackets" is specially proceed in parser, to check "if anyone implement that name, then use the specified method object".
Could anyone can help me to understand how this "curlyBrackets" works from complier perspective? Thanks a lot!
Loading...