Hi,
Here are two new primitives made for
calling primitives. They are useful for
implementing mirrors, smalltalk debugger,
simulator, ...
I've implemented a small example to see
how you can use them.
Cheers,
Gwen
>From 7e5238291182fafcbf8aa11256b5c6ba2bd64c2a Mon Sep 17 00:00:00 2001
From: Gwenael Casaccio <[email protected]>
Date: Thu, 19 Dec 2013 12:05:08 +0100
Subject: [PATCH] Add two primitives VMpr_Object_primitiveOn,
VMpr_Object_primitiveOn WithArguments for calling primitives.
---
ChangeLog | 5 +++
libgst/prims.def | 109 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 114 insertions(+)
diff --git a/ChangeLog b/ChangeLog
index d5395cc..947f32a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2013-12-19 Gwenael Casaccio <[email protected]>
+
+ * libgst/prims.def: Add VMpr_Object_primitiveOnWithArguments and
+ VMpr_Object_primitiveOn primitives.
+
2013-06-14 Jochen Schmitt <[email protected]>
* smalltalk-mode-init.el.in: Use inhibit-local-variables-regexps
diff --git a/libgst/prims.def b/libgst/prims.def
index 7e8eaaf..c75010a 100644
--- a/libgst/prims.def
+++ b/libgst/prims.def
@@ -6211,5 +6211,114 @@ primitive VMpr_Random_next [succeed]
PRIM_FAILED;
}
+/* Object primitive:on:ifFailed:
+ Object primitive:on:with:ifFailed:
+ Object primitive:on:with:withifFailed:
+ Object primitive:on:with:with:with:ifFailed: */
+primitive VMpr_Object_primitiveOn [succeed,fail]
+{
+ OOP oop1, receiver_oop, failed_oop;
+ OOP *oopVec;
+ int i, numPrimitive;
+ _gst_primitives_executed++;
+
+ if (numArgs < 3)
+ PRIM_FAILED;
+
+ oopVec = alloca (numArgs * sizeof (OOP));
+
+ failed_oop = POP_OOP ();
+
+ for (i = 0; i < numArgs - 3; i++)
+ oopVec[i] = POP_OOP ();
+
+ receiver_oop = POP_OOP ();
+
+ oop1 = POP_OOP ();
+ if (!IS_INT (oop1))
+ {
+ UNPOP (numArgs);
+ PRIM_FAILED;
+ }
+
+ numPrimitive = TO_INT (oop1);
+
+ PUSH_OOP (receiver_oop);
+
+ for (i = numArgs - 4; i >= 0; i--)
+ PUSH_OOP (oopVec[i]);
+
+ if COMMON (!execute_primitive_operation(numPrimitive, numArgs - 3))
+ PRIM_SUCCEEDED;
+
+ UNPOP (numArgs - 1);
+
+ PUSH_OOP (oop1);
+ PUSH_OOP (receiver_oop);
+
+ for (i = numArgs - 4; i >= 0; i--)
+ PUSH_OOP (oopVec[i]);
+
+ PUSH_OOP (failed_oop);
+
+ PRIM_FAILED;
+}
+
+/* Object primitive:on:withArguments:ifFailed: */
+primitive VMpr_Object_primitiveOnWithArguments [succeed,fail]
+{
+ OOP oop1;
+ OOP oop2;
+ OOP oop3;
+ OOP receiver_oop;
+ int numPrimitive;
+
+ _gst_primitives_executed++;
+
+ if (numArgs != 4)
+ PRIM_FAILED;
+
+ oop3 = POP_OOP ();
+ oop2 = POP_OOP ();
+ receiver_oop = POP_OOP ();
+ oop1 = POP_OOP ();
+
+ if (!IS_INT (oop1) || !IS_CLASS (oop2, _gst_array_class))
+ {
+ UNPOP (numArgs);
+ PRIM_FAILED;
+ }
+
+ numPrimitive = TO_INT (oop1);
+
+ {
+ OOP result_oop;
+ int i, args;
+ mst_Boolean succeed;
+
+ args = NUM_INDEXABLE_FIELDS (oop2);
+
+ PUSH_OOP (receiver_oop);
+
+ for (i = 1; i <= args; i++)
+ PUSH_OOP (ARRAY_AT (oop2, i));
+
+ if COMMON (!execute_primitive_operation(numPrimitive, args))
+ PRIM_SUCCEEDED;
+
+ for (i = 1; i <= args; i++)
+ POP_OOP ();
+
+ POP_OOP ();
+ }
+
+ PUSH_OOP (oop1);
+ PUSH_OOP (receiver_oop);
+ PUSH_OOP (oop2);
+ PUSH_OOP (oop3);
+
+ PRIM_FAILED;
+}
+
#undef INT_BIN_OP
#undef BOOL_BIN_OP
--
1.8.3.2
Object subclass: Primitive [
primitive: aPrimitive on: anObject ifFailed: aBlock [
<primitive: VMpr_Object_primitiveOn>
^ aPrimitive isSmallInteger
ifFalse: [ SystemExceptions.WrongClass signalOn: aPrimitive mustBe:
SmallInteger ]
ifTrue: [ aBlock value: aPrimitive value: anObject ]
]
primitive: aPrimitive on: anObject with: aParameter1 ifFailed: aBlock [
<primitive: VMpr_Object_primitiveOn>
^ aPrimitive isSmallInteger
ifFalse: [ SystemExceptions.WrongClass signalOn: aPrimitive mustBe:
SmallInteger ]
ifTrue: [ aBlock value: aPrimitive value: anObject value:
aParameter1 ]
]
primitive: aPrimitive on: anObject with: aParameter1 with: aParameter2
ifFailed: aBlock [
<primitive: VMpr_Object_primitiveOn>
^ aPrimitive isSmallInteger
ifFalse: [ SystemExceptions.WrongClass signalOn: aPrimitive mustBe:
SmallInteger ]
ifTrue: [ aBlock valueWithArguments: {aPrimitive. anObject.
aParameter1. aParameter2} ]
]
primitive: aPrimitive on: anObject with: aParameter1 with: aParameter2
with: aParameter3 ifFailed: aBlock [
<primitive: VMpr_Object_primitiveOn>
^ aPrimitive isSmallInteger
ifFalse: [ SystemExceptions.WrongClass signalOn: aPrimitive mustBe:
SmallInteger ]
ifTrue: [ aBlock valueWithArguments: {aPrimitive. anObject.
aParameter1. aParameter2. aParameter3} ]
]
primitive: aPrimitive on: anObject with: aParameter1 with: aParameter2
with: aParameter3 with: aParameter4 ifFailed: aBlock [
<primitive: VMpr_Object_primitiveOn>
^ aPrimitive isSmallInteger
ifFalse: [ SystemExceptions.WrongClass signalOn: aPrimitive mustBe:
SmallInteger ]
ifTrue: [ aBlock valueWithArguments: {aPrimitive. anObject.
aParameter1. aParameter2. aParameter3. aParameter4} ]
]
primitive: aPrimitive on: anObject withArguments: anArray ifFailed: aBlock
[
<primitive: VMpr_Object_primitiveOnWithArguments>
aPrimitive isSmallInteger ifFalse: [ ^ SystemExceptions.WrongClass
signalOn: aPrimitive mustBe: SmallInteger ].
anArray isArray ifFalse: [ ^ SystemExceptions.WrongClass signalOn:
anArray mustBe: Array ].
^ aBlock value: aPrimitive value: anObject value: anArray
]
]
Eval [
| array |
[ (Primitive new primitive: $a on: 1 ifFailed: [ :aPrimitive :anObject |
]). 'KO' printNl. ] on: Error do: [ :err | 'OK' printNl ].
(Primitive new primitive: VMpr_Object_basicAt on: #(14 24 34) ifFailed: [
:aPrimitive :anObject | (aPrimitive == VMpr_Object_basicAt and: [ anObject =
#(14 24 34) ]) ifTrue: [ 'OK' printNl] ifFalse: [ 'KO' printNl ] ]).
(Primitive new primitive: VMpr_Object_class on: 1 ifFailed: [ :aPrimitive
:anObject |'KO' printNl. ]) == SmallInteger ifTrue: [ 'OK' printNl ] ifFalse: [
'KO' printNl ].
(Primitive new primitive: VMpr_Object_basicAt on: #(14 24 34) with: 1
ifFailed: [ :aPrimitive :anObject :arg1 | 'KO' printNl ]) == 14 ifTrue: [ 'OK'
printNl ] ifFalse: [ 'KO' printNl ].
(Primitive new primitive: VMpr_Object_basicAtPut on: #(14 24 34) with: 1
with: 'abc' ifFailed: [ :aPrimitive :anObject :arg1 :arg2 |
(aPrimitive == VMpr_Object_basicAtPut and: [ anObject = #(14 24 34)
and: [ arg1 == 1 and: [ arg2 = 'abc' ] ] ]) ifTrue: [ 'OK' printNl ] ifFalse:
[ 'KO' printNl ] ] ).
array := Array with: 14 with: 24 with: 34.
(Primitive new primitive: VMpr_Object_basicAtPut on: array with: 1 with:
'abc' ifFailed: [ :aPrimitive :anObject :arg1 :arg2 | ] ) = 'abc' ifTrue: [
'OK' printNl] ifFalse: [ 'KO' printNl ].
(array at: 1) = 'abc' ifFalse: [ 'KO' printNl ].
"b VMpr_Object_primitiveOn"
array := Array with: 14 with: 24 with: 34.
(Primitive new primitive: VMpr_Object_basicAt on: array withArguments: #(1)
ifFailed: [ :aPrimitive :anObject :anArray | ]) == 14 ifFalse: [ 'KO' printNl ]
ifTrue: [ 'OK' printNl ].
array := Array with: 14 with: 24 with: 34.
(Primitive new primitive: VMpr_Object_basicAtPut on: array withArguments:
#(1 2) ifFailed: [ :aPrimitive :anObject :anArray | ]).
(array at: 1) == 2 ifTrue: [ 'OK' printNl ] ifFalse: [ 'KO' printNl ].
array := Array with: 14 with: 24 with: 34.
(Primitive new primitive: VMpr_Object_basicAtPut on: #(14 24 34)
withArguments: #(1 2) ifFailed: [ :aPrimitive :anObject :anArray | 'OK' printNl
]).
"b VMpr_Object_primitiveOnWithArguments"
]
_______________________________________________
help-smalltalk mailing list
[email protected]
https://lists.gnu.org/mailman/listinfo/help-smalltalk