smalltalk squeak error: "Instances of undefinedObject are not indexable" - smalltalk

I have problem many time understanding the errors i get in the squeak program, and unable to fix and debug it. like in this case:
I wrote the following code is smalltalk language in squeak:
initilize
super initialize.
path := OrderedCollection new.
-
drawOn: aCanvas
| colors |
colors := Color wheel: 10.
colors withIndexDo:[:c :i |
aCanvas fillOval: (self bounds insetBy: self width/25*i+1 )
color: c
].
-
handlesMouseDown: evt
^true.
-
mouseDown: evt
self position: self position + (10#0).
-
startAnimation
path reset.
0 to: 9 do: [:i | path add: self position +(0#(10*i))].
path := path, path reverse.
self startStepping.
-
step
path size > 0 ifTrue: [self position: path removeFirst].
and this is the code I wrote in the workspace:
myMorph := TestMorph new openInWorld.
but I am getting and error that I wrote up, something about problem with "size" in "step" method
can someone see the problem?

When you get an error message about UndefinedObject it often means that some variable was not initialized correctly, it has the value nil.
The error is that you misspelled initialize
You wrote initilize instead. This method is not called when creating your object and thus the path instance variable is let undefined (nil).

Related

Enforcing and contract methods in Squeak

So I created a class that enforces every method (message) that is sent to it's class instance.
i.e that code:
|a|
a := Animal new.
a makeSound: 'bark'
should lead to a call to "doesNotUnderstand" (even though it exists in the class) and it should check wehther the post and pre conditions are there, i'll explain:
If a method looks like this:
makeSound: aNoise
"%self assert: [canMakeNoise = true]%"
"#self assert: [numOfLegs >= 0]#"
numOfLegs := -1
it means that asside from that main method, there is also a method called: PREmakeSound which is implementation is:
self assert: [canMakeNoise = true]
and onther method called POSTmakeSiund which is implemented as follows:
self assert: [numOfLegs >= 0]
---My question is - because of the fact that every method call is calling doesNotUnderstand, whenever I want to actually activate the method (after I cheked whatever i needed) how can I activate it as is?
hope my problem is clear...
Maybe using method wrappers would work better than using #doesNotUnderstand:?
Create a class PrePostMethod with a compiledMethod instance variable. You can then install instances of PrePostMethod in the method dictionary of a class instead of instances of CompiledMethod.
When the VM looks-up a message and gets this PrePostMethod instance instead of a CompiledMethod, it doesn't know what to do with it. Consequently, it will send "run: aSelector with: arguments in: receiver" to that PrePostMethod object. This is where you can perform custom action like checking pre-post condition.
For example:
PrePostMethod>>run: aSelector with: arguments in: receiver
| result |
self checkPrecondition: receiver
result := compiledMethod run: aSelector with: arguments in: receiver
self checkPostCondition: receiver.
^ result
As Sean suggests, an alternative solution is to change the way these methods are compiled.
You could transform the AST of the method before compilation, or change the compilation process itself. For example, with the AST transformation approach you can transform:
makeSound: aNoise
"%self assert: [ self canMakeNoise]%"
"#self assert: [ self numOfLegs >= 0]#"
numOfLegs := -1
into:
makeSound: aNoise
self assert: [
"The preconditions goes here"
self canMakeNoise ]
^ [ "Original method body + self at the end if there is no return"
numOfLegs := -1.
self ] ensure: [
"The postcondition goes here"
self assert: [ self numOfLegs >= 0 ] ]
One the one hand, these solutions would be more tedious to implement but one the other hand, they are more performant.
HTH
Could you explain more about why you're using doesNotUnderstand? My first thought would be injecting extra byte codes during compilation...
Although, the way to send a message from doesNotUnderstand would be something like:
self perform: newSelector withArguments: aMessage arguments.
The problem is that if this message is that it's easy to get into an infinite loop this way.

Go Initialization operator, package scoped variables - confused:

The following code works correctly - output: You chose Test 1
package main
import (
"fmt"
)
type TNameMap map[int]string
var nameMap TNameMap
func init() {
nameMap = make(TNameMap)
nameMap[1] = "You chose Test 1"
nameMap[2] = "You chose Test 2"
nameMap[3] = "You chose Test 3"
}
func main() {
fmt.Println(nameMap[1])
}
If I comment out the first line in init() i.e //nameMap = make(TNameMap) , I get a panic when main() runs, because nameMap was never initialized:
panic: runtime error: assignment to entry in nil map
But - if in init() I write nameMap := make(TNameMap)
instead of nameMap = make(TNameMap) , I get no panic, but also no output - main() simply runs and process terminates.
I understand that if I use the Initialization operator - nameMap := make(TNameMap) - I have declared a new variable nameMap that is scoped only to the init() function and so only the package level variable var nameMap TNameMap is in scope for main(), resulting in no output, because the package level var holds no map data.
But, I am confused: Why don't I get the panic in that situation? If main() is making the call on the package var, it was never initialized - so why no panic?
According to the Go spec:
A nil map is equivalent to an empty map except that no elements may be
added.
This means that you can read from a nil map, but not write. Just like the panic says "assignment to entry in nil map". If you comment out just the line nameMap = make(TNameMap) it will crash because you attempt to write to it in init (which is where the panic happens). If you comment out the entirety of init the Println will not crash because you're permitted to access (read from) a nil map.
Changing the assignment to a declaration is just masking the real issue here, what's happening is it's making all the assignments valid, and then discarding the result. As long as you make the assignments valid (either by removing them or making a temporary variable), then you will observe the same behavior in Println.
The value returned by a nil map is always the zero value of the value type of the map. So a map[T]string returns "", a map[T]int returns 0, and so on. (Of course, if you check with val,ok := nilMap[key] then ok will be false).

Creating Lua objects during callback issue

I making simple project on Delphi + Lua to use Delphi visual components through RTTI. Main implementation idea based on luna.h. I like Blizzard's idea of using templates stored in xml (when you can put several objects on TPanel for example and use it as template), so I almost implemented that also.
The problem is: everything works fine until I creating objects through callback from Lua made with almost same code as luna.h Inject code. If this object have "inherits" xml attribute callback function calls creation of objects stored in xml, creating another object through yet another injection. And I receive errors leading to lua51.dll.
Maybe that problem caused by using stack by both callback and Inject while callback function not returned result yet. So can I use stack and create objects through callback? If not - is there any workarounds to implement it? Blizzard really made it somehow.
More details:
1. Application registering Lua objects (for example TPanel and many others) through
cn := T.ClassName;
f := #StaticOnCreate;
lua_pushlightuserdata(L, self); // put offset to self into lightuserdata
lua_pushcclosure(L, f, 1);
lua_setglobal(L, PAnsiChar(UTF8Encode(cn))); // T() in lua will make a new instance.
difference from luna.h - application also stored pointer to object (Delphi objects are pointers) to avoid generics (c templates)
2. Now Lua have TPanel in global table
3. By using
p = TPanel("somename")
in script, Lua calls application's StaticOnCreate.
4. StaticOnCreate extracts object and calls class's function
o := TLuaClassTemplate(lua_topointer(L, lua_upvalueindex(1)));
result := o.OnCreate(L);
5. OnCreate function extracts params like name etc and creates exact visual object of type TPanel and by using same code as luna.h for inject function
lua_newtable(FL); // create a new table for the class object ('self')
obj_index := lua_gettop(FL);
lua_pushnumber(FL, 0);
a := lua_newuserdata(FL, SizeOf(pointer)); // store a ptr to the ptr
a^ := obj; // set the ptr to the ptr to point to the ptr... >.>
luaL_newmetatable(FL, PAnsiChar(UTF8Encode(cn))); // get (or create) the classname_metatable
lua_pushstring(FL, PAnsiChar(UTF8Encode('__gc')));
lua_pushlightuserdata(FL, self); // put offset to self into lightuserdata
lua_pushcclosure(FL, #StaticGc_T, 1);
lua_settable(FL, -3);
lua_setmetatable(FL, -2); // userdata.metatable = classname_metatable
lua_settable(FL, obj_index); // self[0] = obj;
f := #StaticThunk;
// register the functions
for i := 0 to length(ClassApiArray) - 1 do begin
lua_pushstring(FL, PAnsiChar(UTF8Encode(ClassApiArray[i].name)));
lua_pushlightuserdata(FL, self); // put offset to self into lightuserdata
lua_pushnumber(FL, i); // let the thunk know which method we mean
lua_pushcclosure(FL, f, 2);
lua_settable(FL, obj_index); // self["function"] = thunk("function")
end;
lua_pushvalue(FL, -1); // dup object on stack top
rec.ref := luaL_ref(FL, LUA_REGISTRYINDEX); // store object as ref
...
result := 1;
returns Lua object through stack, so now p from p = TPanel("somename") is object isntance.
But issue if I trying to implement xml templates and step 3
p = TPanel("somename", "xmltemplatenodename")
and during execution step 5 in OnCreate if I see there is inherits = xmltemplatenodename. So during step 5, before inject, application searching for exact xmltemplatenodename - if found creating more objects with inject for each object. And only after that continues execution of step 5 with own inject. Here I have errors leading to lua51.dll after creating 2-3 objects from xmltemplatenodename. But if application uses same xml as source and creates same xmltemplatenodename objects outside of OnCreate - there is no errors.
Inject for xml object slightly different, isntead of leaving object in stack it registers it by object name
lua_setglobal(FL, PAnsiChar(objName8));

"return" from method while stepping?

I would like to exit out the current method that I'm stepping through.
-(void)helloWorld {
NSLog(#"Hello");
// I would like to return here, so that "World" isn't printed.
NSLog(#"World");
}
I have tried the following, but without luck.
(lldb) expr return
<no result>
Is this possible with lldb?
Unfortunately in Xcode 4.5.x there is no way to force an early return from a function. In the current lldb sources over at http://lldb.llvm.org/ there is a newly added command, thread return, which does what you want - it includes the ability to specify the return value of the function. This won't be in Xcode until the next major release, though.
When you are debugging using Xcode and when your program is paused at a breakpoint, you can drag the little green arrow to any other line in the function. E.g. in the following code:
if I want to skip the NSLog(#"B"), I can simply drag the green arrow from line 20 to line 23, which means the function will simply "return" from anywhere I want.
I just added a breakpoint at the line mentioned below:
var computed: Bool {
return device.time == 10 // added breakpoint here
}
and got the following error:
error: Error returning from frame 0 of thread 1: We only support
setting simple integer and float return types at present..
Seems to work for only those two types

NSFormatter and NSTokenField and setting the maximum length

I would like to use a custom NSFormatter to judge the length of a string inside of a NSTokenField.
I have implemented the NSFormatter and hooked it up within the xib and all that, now when I get to running my application with the formatter inplace connected to the NSTokenField I get this error:
2011-12-31 18:15:11.761 MyApp[4706:a0f] -[NSCFArray length]: unrecognized selector sent to instance 0xf4a530
(gdb) describe 0xf4a530
Undefined command: "describe". Try "help".
(gdb) p 0xf4a530
$1 = 16033072
(gdb) po 0xf4a530
<NSCFArray 0xf4a530>(
{
Format = "%01d";
FormatIndex = 0;
Name = "$Counter$";
},
{
Format = "";
Name = hey;
}
)
Now I understand that indeed the textcell being evaluated contains an array of items so I will need to probably turn these to a string but the place where this is erroring in my code is here:
//Set this so that user can't enter a super long amount and overflow the character array lower in the engine.
[fieldFormatter setMaximumLength:40];
Im just evaluating the fieldFormatter object and setting its member variable of int to 40... really shouldnt be evaluating the text yet... right?