2 docCopyright("Jonathan Wright; Steve Dekorte (2002)", 2006)
3 docLicense("BSD revised")
6 #include "IoMessage_opShuffle.h"
10 #define DATA(self) ((IoMessageData *)IoObject_dataPointer(self))
12 IoMap
*IoState_createOperatorTable(IoState
*state
)
14 typedef struct OpTable
{
63 IoMap
*self
= IoMap_new(state
);
68 IoMap_rawAtPut(self
, IOSYMBOL(op
->symbol
), IONUMBER(op
->precedence
));
75 IoMap
*IoState_createAssignOperatorTable(IoState
*state
)
90 IoMap
*self
= IoMap_new(state
);
95 IoMap_rawAtPut(self
, IOSYMBOL(op
->symbol
), IOSYMBOL(op
->name
));
103 // TODO move the IO_OP_MAX_LEVEL define to be adjacent to the op table.
104 // TODO Set IO_OP_MAX_LEVEL to max-1 or something massive otherwise people playing with custom operators don't have many levels available
105 #define IO_OP_MAX_LEVEL 17
107 enum LevelType
{ATTACH
, ARG
, NEW
, UNUSED
};
115 void Level_finish(Level
*self
);
116 void Level_attachAndReplace(Level
*self
, IoMessage
*msg
);
117 void Level_setAwaitingFirstArg(Level
*self
, IoMessage
*msg
, int precedence
);
120 Level pool
[IO_OP_MAX_LEVEL
];
124 IoMap
*operatorTable
;
125 IoMap
*assignOperatorTable
;
128 void Levels_reset(Levels
*self
)
131 self
->currentLevel
= 1;
133 for (i
= 0; i
< IO_OP_MAX_LEVEL
; i
++)
135 Level
*level
= &self
->pool
[i
];
136 level
->type
= UNUSED
;
140 Level
*level
= &self
->pool
[0];
141 level
->message
= NULL
;
143 level
->precedence
= IO_OP_MAX_LEVEL
;
146 List_removeAll(self
->stack
);
147 List_append_(self
->stack
, &self
->pool
[0]);
150 // --- Levels ----------------------------------------------------------
152 Levels
*Levels_new(IoMessage
*msg
)
154 Levels
*self
= io_calloc(1, sizeof(Levels
));
156 IoState
*state
= IoObject_state(msg
);
157 IoSymbol
*operatorTableSymbol
= IoState_symbolWithCString_(state
, "OperatorTable");
159 // Lets be ultra flexable, and try to use the first message's operator table.
160 IoObject
*opTable
= IoObject_rawGetSlot_(msg
, operatorTableSymbol
);
162 // Otherwise, use Core OperatorTable, and if that doesn't exist, create it.
165 // There is a chance the message didn't have it, but the core did---due
166 // to the Core not being part of the message's protos. Use Core
167 // Message's OperatorTable
168 opTable
= IoObject_rawGetSlot_(state
->core
, operatorTableSymbol
);
170 // If Core doesn't have an OperatorTable, lets create it.
173 opTable
= IoObject_new(state
);
174 IoObject_setSlot_to_(state
->core
, operatorTableSymbol
, opTable
);
179 IoSymbol
*operatorsSymbol
= IoState_symbolWithCString_(state
, "operators");
180 IoObject
*operators
= IoObject_rawGetSlot_(opTable
, operatorsSymbol
);
182 if (operators
&& ISMAP(operators
))
184 self
->operatorTable
= operators
;
188 // Not strictly correct as if the message has it's own empty
189 // OperatorTable slot, we'll create one for it instead of using
190 // Core Message OperatorTable operators. Oh well.
192 self
->operatorTable
= IoState_createOperatorTable(state
);
193 IoObject_setSlot_to_(opTable
, operatorsSymbol
, self
->operatorTable
);
198 IoSymbol
*assignOperatorsSymbol
= IoState_symbolWithCString_(state
, "assignOperators");
199 IoObject
*assignOperators
= IoObject_rawGetSlot_(opTable
, assignOperatorsSymbol
);
201 if (assignOperators
&& ISMAP(assignOperators
))
203 self
->assignOperatorTable
= assignOperators
;
207 // Not strictly correct as if the message has it's own empty
208 // OperatorTable slot, we'll create one for it instead of using
209 // Core Message OperatorTable operators. Oh well.
211 self
->assignOperatorTable
= IoState_createAssignOperatorTable(state
);
212 IoObject_setSlot_to_(opTable
, assignOperatorsSymbol
, self
->assignOperatorTable
);
216 self
->stack
= List_new();
221 void Levels_free(Levels
*self
)
223 List_free(self
->stack
);
227 inline Level
*Levels_currentLevel(Levels
*self
)
229 return List_top(self
->stack
);
232 void Levels_popDownTo(Levels
*self
, int targetLevel
)
236 while (level
= List_top(self
->stack
), level
->precedence
<= targetLevel
&& level
->type
!= ARG
)
238 Level_finish(List_pop(self
->stack
));
239 self
->currentLevel
--;
243 void Levels_attachToTopAndPush(Levels
*self
, IoMessage
*msg
, int precedence
)
247 Level
*top
= List_top(self
->stack
);
248 Level_attachAndReplace(top
, msg
);
252 // TODO: Check for overflow of the pool.
253 if (self
->currentLevel
>= IO_OP_MAX_LEVEL
)
255 IoState_error_(IoObject_state(msg
), NULL
, "compile error: Overflowed operator stack. Only %d levels of operators currently supported.", IO_OP_MAX_LEVEL
-1);
258 level
= &self
->pool
[self
->currentLevel
++];
259 Level_setAwaitingFirstArg(level
, msg
, precedence
);
260 List_append_(self
->stack
, level
);
264 void Level_finish(Level
*self
)
268 IoMessage_rawSetNext(self
->message
, NULL
);
270 // Remove extra () we added in for operators, but don't need any more
271 if ( IoMessage_argCount(self
->message
) == 1 )
273 IoMessage
*arg
= IoMessage_rawArgAt_(self
->message
, 0);
275 if ( IoSeq_rawSize(IoMessage_name(arg
)) == 0 && IoMessage_argCount(arg
) == 1 && IoMessage_rawNext(arg
) == NULL
)
277 List_copy_(IoMessage_rawArgList(self
->message
), IoMessage_rawArgList(arg
));
278 List_removeAll(IoMessage_rawArgList(arg
));
286 void Level_attach(Level
*self
, IoMessage
*msg
)
291 IoMessage_rawSetNext(self
->message
, msg
);
295 IoMessage_addArg_(self
->message
, msg
);
307 void Level_attachAndReplace(Level
*self
, IoMessage
*msg
)
309 Level_attach(self
, msg
);
314 void Level_setAwaitingFirstArg(Level
*self
, IoMessage
*msg
, int precedence
)
318 self
->precedence
= precedence
;
321 void Level_setAlreadyHasArgs(Level
*self
, IoMessage
*msg
)
327 int Levels_levelForOp(Levels
*self
, char *messageName
, IoSymbol
*messageSymbol
, IoMessage
*msg
)
329 IoObject
*value
= IoMap_rawAt(self
->operatorTable
, messageSymbol
);
338 return IoNumber_asInt((IoNumber
*)value
);
342 IoState_error_(IoObject_state(msg
), msg
, "compile error: Value for '%s' in Message OperatorTable operators is not a number. Values in the OperatorTable operators are numbers which indicate the precedence of the operator.", messageName
);
343 return -1; // To keep the compiler happy.
347 int Levels_isAssignOperator(Levels
*self
, IoSymbol
*operator)
349 return IoMap_rawAt(self
->assignOperatorTable
, operator) != NULL
;
352 IoSymbol
*Levels_nameForAssignOperator(Levels
*self
, IoState
*state
, IoSymbol
*operator, IoSymbol
*slotName
, IoMessage
*msg
)
354 IoObject
*value
= IoMap_rawAt(self
->assignOperatorTable
, operator);
355 char *operatorString
= CSTRING(operator);
357 if (value
!= NULL
&& ISSYMBOL(value
))
359 if (strcmp(operatorString
, ":=") == 0 && isupper(CSTRING(slotName
)[0]))
361 return state
->setSlotWithTypeSymbol
;
370 IoState_error_(IoObject_state(msg
), msg
, "compile error: Value for '%s' in Message OperatorTable assignOperators is not a symbol. Values in the OperatorTable assignOperators are symbols which are the name of the operator.", operatorString
);
371 return NULL
; // To keep the compiler happy.
375 void Levels_attach(Levels
*self
, IoMessage
*msg
, List
*expressions
)
377 // TODO clean up this method.
379 IoState
*state
= IoObject_state(msg
);
380 IoSymbol
*messageSymbol
= IoMessage_name(msg
);
381 char *messageName
= CSTRING(messageSymbol
);
382 int precedence
= Levels_levelForOp(self
, messageName
, messageSymbol
, msg
);
384 int msgArgCount
= IoMessage_argCount(msg
);
386 // `o a := b c ; d` becomes `o setSlot("a", b c) ; d`
392 if (Levels_isAssignOperator(self
, messageSymbol
))
394 Level
*currentLevel
= Levels_currentLevel(self
);
395 IoMessage
*attaching
= currentLevel
->message
;
396 IoSymbol
*setSlotName
;
398 if (attaching
== NULL
) // `:= b ;`
400 // Could be handled as, message(:= 42) -> setSlot(nil, 42)
402 IoState_error_(state
, msg
, "compile error: %s requires a symbol to its left.", messageName
);
405 if (IoMessage_argCount(attaching
) > 0) // `a(1,2,3) := b ;`
407 IoState_error_(state
, msg
, "compile error: The symbol to the left of %s cannot have arguments.", messageName
);
413 IoSymbol
*slotName
= DATA(attaching
)->name
;
414 IoSymbol
*quotedSlotName
= IoSeq_newSymbolWithFormat_(state
, "\"%s\"", CSTRING(slotName
));
415 IoMessage
*slotNameMessage
= IoMessage_newWithName_returnsValue_(state
, quotedSlotName
, slotName
);
417 // `a := b ;` -> `a("a") := b ;`
418 IoMessage_addArg_(attaching
, slotNameMessage
);
420 setSlotName
= Levels_nameForAssignOperator(self
, state
, messageSymbol
, slotName
, msg
);
423 // `a("a") := b ;` -> `setSlot("a") := b ;`
424 DATA(attaching
)->name
= IoObject_addingRef_(attaching
, setSlotName
);
426 currentLevel
->type
= ATTACH
;
428 if (msgArgCount
> 1) // `setSlot("a") :=(b, c, d) e ;`
430 IoState_error_(state
, msg
, "compile error: Assign operator passed multiple arguments, e.g., a := (b, c).", messageName
);
433 if (msgArgCount
> 0) // `setSlot("a") :=(b c) d e ;`
436 IoMessage
*arg
= IoMessage_rawArgAt_(msg
, 0);
438 if (DATA(msg
)->next
== NULL
|| IoMessage_rawIsEOL(DATA(msg
)->next
))
440 IoMessage_addArg_(attaching
, arg
);
445 IoMessage
*foo
= IoMessage_newWithName_(state
, IoState_symbolWithCString_(state
, ""));
448 IoMessage_addArg_(foo
, arg
);
450 // `(b c)` -> `(b c) d e ;`
451 IoMessage_rawSetNext(foo
, DATA(msg
)->next
);
453 // `setSlot("a") :=(b c) d e ;` -> `setSlot("a", (b c) d e ;) :=(b c) d e ;`
454 IoMessage_addArg_(attaching
, foo
);
457 else // `setSlot("a") := b ;`
459 // `setSlot("a") :=` or `setSlot("a") := ;`
460 IoMessage
*mn
= DATA(msg
)->next
;
461 IoSymbol
*name
= mn
? DATA(mn
)->name
: NULL
;
462 IoSymbol
*semi
= IoObject_state(msg
)->semicolonSymbol
;
464 //if (mn == NULL || IoMessage_rawIsEOL(mn))
465 if (mn
== NULL
|| name
== semi
)
467 IoState_error_(state
, msg
, "compile error: %s must be followed by a value.", messageName
);
470 // `setSlot("a") := b c ;` -> `setSlot("a", b c ;) := b c ;`
471 IoMessage_addArg_(attaching
, DATA(msg
)->next
);
474 // process the value (`b c d`) later (`setSlot("a", b c d) := b c d ;`)
475 if (DATA(msg
)->next
!= NULL
&& !IoMessage_rawIsEOL(DATA(msg
)->next
))
477 List_push_(expressions
, DATA(msg
)->next
);
481 IoMessage
*last
= msg
;
482 while (DATA(last
)->next
!= NULL
&& !IoMessage_rawIsEOL(DATA(last
)->next
))
484 last
= DATA(last
)->next
;
487 IoMessage_rawSetNext(attaching
, DATA(last
)->next
);
489 // Continue processing in IoMessage_opShuffle loop
490 IoMessage_rawSetNext(msg
, DATA(last
)->next
);
494 IoMessage_rawSetNext(last
, NULL
);
498 // make sure b in `1 := b` gets executed
499 IoMessage_cachedResult_(attaching
, NULL
);
501 else if (IoMessage_rawIsEOL(msg
))
503 Levels_popDownTo(self
, IO_OP_MAX_LEVEL
-1);
504 Level_attachAndReplace(Levels_currentLevel(self
), msg
);
506 else if (precedence
!= -1) // is an operator
510 // move arguments off to their own message to make () after operators behave like C's grouping ()
511 IoMessage
*brackets
= IoMessage_newWithName_(state
, IoState_symbolWithCString_(state
, ""));
513 List_copy_(IoMessage_rawArgList(brackets
), IoMessage_rawArgList(msg
));
514 List_removeAll(IoMessage_rawArgList(msg
));
516 // Insert the brackets message between msg and it's next message
517 IoMessage_rawSetNext(brackets
, DATA(msg
)->next
);
518 IoMessage_rawSetNext(msg
, brackets
);
521 Levels_popDownTo(self
, precedence
);
522 Levels_attachToTopAndPush(self
, msg
, precedence
);
526 Level_attachAndReplace(Levels_currentLevel(self
), msg
);
530 void Levels_nextMessage(Levels
*self
)
534 while ((level
= List_pop(self
->stack
)))
542 void IoMessage_opShuffle_(IoMessage
*self
)
544 if (IoObject_rawGetSlot_(self
, IOSTATE
->opShuffleSymbol
) && IoMessage_name(self
) != IOSTATE
->noShufflingSymbol
)
546 IoMessage_locals_performOn_(IOSTATE
->opShuffleMessage
, IOSTATE
->lobby
, self
);
550 IoMessage
*IoMessage_opShuffle(IoMessage
*self
, IoObject
*locals
, IoMessage
*m
)
552 Levels
*levels
= Levels_new(self
);
553 List
*expressions
= List_new();
555 List_push_(expressions
, self
);
557 while (List_size(expressions
) >= 1)
559 IoMessage
*n
= List_pop(expressions
);
563 Levels_attach(levels
, n
, expressions
);
564 List_appendSeq_(expressions
, DATA(n
)->args
);
565 } while (n
= DATA(n
)->next
);
567 Levels_nextMessage(levels
);
570 List_free(expressions
);