$print {Demonstrating Object support...}
/**
TODO: figure out why this script, when run via the fossi1ish
interpreter (which adds 80-100kb of memory in infrastructure)
somehow needs 1.2MB instead of the 85kb it needs when run in
the standalone th1ish on my 64-bit box? The main difference is
that it is being import()ed there, but other scripts do not show
such a drastic difference due just to an environment change.
*/
const magicValue 42
const obj object {
a:7,
b:9.2+3,
f: proc {a} {
$print "from member:" a
//$print 'argv =' argv
assert a === argv.0
assert (undefined===a) || (1===[argv.length])
return magicValue
},
o: object { "hi!": "world" }
}
assert magicValue === $(get obj 'f') "got"
1 && scope {
var f obj.f
assert 'function' === typename f
//$print 'f =' f
set f.foo 'bar'
assert magicValue === $f "hi"
//$print 'f =' f
//$print 'obj =' obj
//$print 'obj.a =' obj.a
//$print 'obj.o."hi!" =' obj.o."hi!"
assert "world" === obj.o."hi!"
}
1 && scope {
set obj.p print
set obj.o.p print
$obj.o.p "via $obj.o.p"
}
1 && scope {
var ar = array[1,2,3]
assert 'function' === typename ar.length
assert 3 === [ar.length]
assert 3 === $ar.length
assert 4 === [ar.length 4]
set ar.6 '#6'
assert '#6' === ar.(5+2-1)
set ar.foo 'foobar'
assert 7 === [ar.length]
assert 'foobar' === ar.foo
//$print 'ar =' ar
assert unset ar.foo
assert !unset ar.foo
assert undefined === ar.foo
var ex = catch { [ar.length "hi"] }
$print typename ex ex
assert 'exception' === typename ex
$print "Caught expected exception:" ex
}
1 && scope {
set obj.o2 obj
assert obj === obj.o2
set obj.o.'p' print
assert print === obj.o.p
set obj.o2.inner 17
assert 17 === obj.o2.inner
assert 7 === obj.o2.a
set obj.(obj) obj
assert obj === obj.(obj)
assert 'object' === typename (obj.(obj))
assert undefined === obj.(null)
set obj.o.3 19
assert 19 === obj.o.3
assert 'double' === typename obj.(obj).b
assert 'double' === typename obj.(obj).{b}
//$print 'obj.(SELF).b =' obj.(obj).b
//$print 'obj.(obj)."b" =' obj.(obj)."b"
assert 42 === $obj.o2.f //via $obj.o2.f
}
1 && scope {
assert undefined === obj.unknown // must not throw
//$print 'obj.unknown =' obj.unknown
var exp = catch { obj.unknown.foo }
assert 'exception' === typename exp
$print "Got expected exception:" exp
set exp catch {
/* Ensure that (...) disables unknown-identifier
fudging. */
obj.(unknown)
}
assert 'exception' === typename exp
$print "Got expected exception:" exp
//throw exp
//throw exp.message
//scope { throw exp }
//not reached;
}
1 && scope {
var o2 = object {
a:3,
f: proc{} {
//$print 'this =' this
//$print 'this.a =' this.a
//$print 'argv =' argv
assert argv.callee === this.f
assert 3 === this.a
},
list: array[6,7,8,9]
}
[o2.f]
assert 4 === $o2.list.length
assert 9 === o2.list.3
assert undefined === o2.list.4
//$print 'o2.list =' o2.list
set o2.list.4 12
assert 12 === o2.list.4
//$print 'o2.list =' o2.list
assert 'exception' === typename var ex catch {
set o2.f.ff o2.f
$o2.f.ff // will fail on (argv.callee===this.f) check
}
assert 'CWAL_RC_ASSERT' === [ex.codeString]
$print "Got expected exception:" ex
}
1 && scope {
var a array [007, 0xf, 1.3];
set a.setLength proc {newLen} {
assert 1 === $argv.length
return $this.length newLen
}
set a.f function {} {
//$print 'this =' this
//$print 'this.prototype =' this.prototype
assert 'object' === typename this.prototype
assert 'object' === typename this.prototype.prototype
assert 'world' === argv.callee.33
}
//$print '[a.propertyKeys] =' [a.propertyKeys]
assert 2 === [[a.propertyKeys].length]
//assert 2 === [[a.propertyKeys.apply a].length]
assert 'world' === a.f.33 = 'world'
[a.f]
assert 'function' === typename a.length
assert a.length === a.prototype.length
assert 'CWAL_RC_TYPE' === [catch { [a.prototype.length] }.codeString] // b/c prototype is-not-a Array
assert 5 === $a.setLength 5
assert 5 === $a.length
set a.([a.length]-1) 'TheEnd'
assert 'TheEnd' === a.([a.length]-1)
assert 'No, really' === [a.set [a.length] 'No, really']
assert 'No, really' === a.([a.length]-1)
assert [a.unset [a.length]-1]
assert undefined === a.([a.length]-1)
assert 'CWAL_RC_RANGE' === [catch {[a.set -1 3]}.codeString]
//$print a
var i 0, z = 0
$a.eachIndex proc {v,i} {
//$print '#' i '=' v
z += 1
}
assert z === [a.length]
set a.foo = "foo"
set a.bar = "bar"
set a.(a) = a
set z 0
$print "Property list:"
$a.eachProperty proc {k,v}{
$print '\t' k '=' v
set z z + 1
}
assert z === 5 /* including the functions set above */
var obj object {}
set obj.eachIndex a.eachIndex
assert 'CWAL_RC_TYPE' ===
[catch{ $obj.eachIndex proc {} {} }.codeString] // wrong type for eachIndex() impl
}
1 && scope {
var max 3, count = 0
var f proc {i=0} {
set count i
if {i<max} {
//$print "Recursing..."
[argv.callee i+1]
}
}
$f
assert max === count
}
1 && scope {
const obj object{}
obj . foo = 1
assert 1 === obj.foo
obj.
foo = 2
assert 2 === obj.foo
obj /* comments are
ignored*/
.foo = 3 // didn't expect this to work b/c of newline b/t them
assert 3 === obj.foo // but hey, why not?
}
scope {
const obj = object {
p1: object{d: 4, a:1, c:2, b:3}
}
const sorter = proc(k,v){
print("Sorting",k)
const ce = argv.callee
print("ce:",typename ce)
assert 'function' === typename ce
assert ce.isTheSorter
if('object' === typename v){
[v.sortProperties]
[v.eachProperty ce]
//v.eachProperty.call( v, ce )
//v.eachProperty(ce)
//$v.eachProperty ce
/*
This isa th1ish bug (in several places, it turns out):
eachProperty() does not override the argv/this vars,
so we're inheriting them (which is correct for 'this',
but not argv.
Would bite other algos similarly. Fixed now:
cwal_callback_hook_set() was added to deal with this
generically.
*/
}
}
sorter.isTheSorter = true
$obj.eachProperty sorter
//[print obj]
const keys = [obj.p1.propertyKeys]
assert 4 === [keys.length]
assert 'a' === keys.0
assert 'd' === keys.3
}
$print "Done with script #7"
return obj.o