/interpreter/tags/at2dist130208/test/edu/vub/at/objects/natives/grammar/TestEval.java
Java | 321 lines | 238 code | 55 blank | 28 comment | 0 complexity | 01f887556bdaac0a3b1fec08b53c20f4 MD5 | raw file
1package edu.vub.at.objects.natives.grammar; 2 3import edu.vub.at.AmbientTalkTest; 4import edu.vub.at.actors.ATAsyncMessage; 5import edu.vub.at.exceptions.InterpreterException; 6import edu.vub.at.exceptions.XSelectorNotFound; 7import edu.vub.at.exceptions.XUndefinedSlot; 8import edu.vub.at.objects.ATAbstractGrammar; 9import edu.vub.at.objects.ATClosure; 10import edu.vub.at.objects.ATContext; 11import edu.vub.at.objects.ATMessage; 12import edu.vub.at.objects.ATMethod; 13import edu.vub.at.objects.ATMethodInvocation; 14import edu.vub.at.objects.ATObject; 15import edu.vub.at.objects.ATTable; 16import edu.vub.at.objects.grammar.ATSymbol; 17import edu.vub.at.objects.natives.NATClosure; 18import edu.vub.at.objects.natives.NATMethod; 19import edu.vub.at.objects.natives.NATNumber; 20import edu.vub.at.objects.natives.NATObject; 21import edu.vub.at.objects.natives.NATTable; 22import edu.vub.at.objects.natives.NATText; 23import edu.vub.at.objects.natives.OBJNil; 24 25/** 26 * Tests the ATObject.meta_eval(ATContext) method for different kinds of abstract grammar elements. 27 */ 28public class TestEval extends AmbientTalkTest { 29 30 public static void main(String[] args) { 31 junit.swingui.TestRunner.run(TestEval.class); 32 } 33 34 private final NATNumber atThree_ = NATNumber.atValue(3); 35 private final AGSymbol atX_ = AGSymbol.alloc(NATText.atValue("x")); 36 private final AGSymbol atY_ = AGSymbol.alloc(NATText.atValue("y")); 37 private final AGSymbol atZ_ = AGSymbol.alloc(NATText.atValue("z")); 38 private final AGSymbol atM_ = AGSymbol.alloc(NATText.atValue("m")); 39 private final AGSymbol atFooBar_ = AGSymbol.alloc(NATText.atValue("foo:bar:")); 40 41 // statements 42 43 public void testBegin() { 44 evalAndCompareTo("1; 2; 3", atThree_); 45 evalAndCompareTo("3", atThree_); 46 } 47 48 // definitions 49 50 public void testDefField() throws InterpreterException { 51 evalAndCompareTo("def x := 3", atThree_); 52 assertEquals(atThree_, ctx_.base_lexicalScope().impl_call(atX_, NATTable.EMPTY)); 53 } 54 55 public void testDefFunction() throws InterpreterException { 56 evalAndCompareTo("def x() { 3 }", "<closure:x>"); 57 try { 58 ATClosure clo = ctx_.base_lexicalScope().impl_lookup(atX_).asClosure(); 59 assertEquals(atX_, clo.base_method().base_name()); 60 } catch(XSelectorNotFound e) { 61 fail("broken definition:"+e.getMessage()); 62 } 63 } 64 65 public void testDefTable() throws InterpreterException { 66 evalAndCompareTo("def x[3] { 1; 2; 3 }", "[3, 3, 3]"); 67 try { 68 ATObject tab = ctx_.base_lexicalScope().impl_call(atX_, NATTable.EMPTY); 69 assertEquals(atThree_, tab.asTable().base_length()); 70 assertEquals(atThree_, tab.asTable().base_at(NATNumber.ONE)); 71 } catch(XSelectorNotFound e) { 72 fail("broken definition:"+e.getMessage()); 73 } 74 } 75 76 public void testDefExternalMethod() throws InterpreterException { 77 ATObject rcvr = new NATObject(); 78 AGSymbol rcvnam = AGSymbol.jAlloc("o"); 79 ctx_.base_lexicalScope().meta_defineField(rcvnam, rcvr); 80 evalAndCompareTo("def o.x() { self }", "<closure:x>"); 81 try { 82 ATClosure clo = rcvr.impl_lookup(atX_).asClosure(); 83 assertEquals(atX_, clo.base_method().base_name()); 84 assertEquals(rcvr, rcvr.meta_invoke(rcvr, atX_, NATTable.EMPTY)); 85 } catch(XSelectorNotFound e) { 86 fail("broken external method definition:"+e.getMessage()); 87 } 88 } 89 90 public void testDefExternalField() throws InterpreterException { 91 ATObject rcvr = new NATObject(); 92 AGSymbol rcvnam = AGSymbol.jAlloc("o2"); 93 ctx_.base_lexicalScope().meta_defineField(rcvnam, rcvr); 94 evalAndCompareTo("def o2.x := 3", atThree_); 95 try { 96 assertEquals(atThree_, rcvr.impl_invokeAccessor(rcvr, atX_, NATTable.EMPTY)); 97 } catch(XUndefinedSlot e) { 98 fail("broken external field definition:"+e.getMessage()); 99 } 100 } 101 102 // assignments 103 104 public void testAssignVariable() throws InterpreterException { 105 // def x := nil 106 ctx_.base_lexicalScope().meta_defineField(atX_, OBJNil._INSTANCE_); 107 108 evalAndCompareTo("x := 3", atThree_); 109 assertEquals(atThree_, ctx_.base_lexicalScope().impl_call(atX_, NATTable.EMPTY)); 110 } 111 112 public void testAssignTable() throws InterpreterException { 113 // def x[2] { nil } 114 ATTable table = NATTable.atValue(new ATObject[] { OBJNil._INSTANCE_, OBJNil._INSTANCE_ }); 115 ctx_.base_lexicalScope().meta_defineField(atX_, table); 116 117 evalAndCompareTo("x[1] := 3", atThree_); 118 assertEquals(atThree_, table.base_at(NATNumber.ONE)); 119 } 120 121 public void testAssignField() throws InterpreterException { 122 // def x := object: { def y := 0 } 123 ATObject x = new NATObject(ctx_.base_lexicalScope()); 124 x.meta_defineField(atY_, NATNumber.ZERO); 125 ctx_.base_lexicalScope().meta_defineField(atX_, x); 126 127 evalAndCompareTo("x.y := 3", atThree_); 128 assertEquals(atThree_, x.impl_invokeAccessor(x, atY_, NATTable.EMPTY)); 129 } 130 131 public void testMultiAssignment() throws InterpreterException { 132 // def x := 1; def y := 3 133 ctx_.base_lexicalScope().meta_defineField(atX_, NATNumber.ONE); 134 ctx_.base_lexicalScope().meta_defineField(atY_, atThree_); 135 136 evalAndCompareTo("[x, y] := [ y, x ]", "[3, 1]"); 137 assertEquals(atThree_, ctx_.base_lexicalScope().impl_call(atX_, NATTable.EMPTY)); 138 assertEquals(NATNumber.ONE, ctx_.base_lexicalScope().impl_call(atY_, NATTable.EMPTY)); 139 } 140 141 // expressions 142 143 public void testSymbolReference() throws InterpreterException { 144 // def x := 3 145 ctx_.base_lexicalScope().meta_defineField(atX_, atThree_); 146 evalAndCompareTo("x", atThree_); 147 } 148 149 public void testTabulation() throws InterpreterException { 150 // def x := [3,1] 151 ATTable table = NATTable.atValue(new ATObject[] { atThree_, NATNumber.ONE }); 152 ctx_.base_lexicalScope().meta_defineField(atX_, table); 153 154 evalAndCompareTo("x[1]", atThree_); 155 evalAndCompareTo("x[2]", NATNumber.ONE); 156 } 157 158 public void testClosureLiteral() throws InterpreterException { 159 ATClosure clo = evalAndReturn("{| x, y | 3 }").asClosure(); 160 ATSymbol nam = clo.base_method().base_name(); 161 ATTable arg = clo.base_method().base_parameters(); 162 ATAbstractGrammar bdy = clo.base_method().base_bodyExpression(); 163 ATContext ctx = clo.base_context(); 164 assertEquals(AGSymbol.alloc(NATText.atValue("lambda")), nam); 165 assertEquals(atX_, arg.base_at(NATNumber.ONE)); 166 assertEquals(atY_, arg.base_at(NATNumber.atValue(2))); 167 assertEquals(atThree_, bdy.asBegin().base_statements().base_at(NATNumber.ONE)); 168 assertEquals(ctx_, ctx); 169 } 170 171 public void testSelfReference() throws InterpreterException { 172 evalAndCompareTo("self", ctx_.base_self()); 173 } 174 175 public void testSuperReference() throws InterpreterException { 176 assertEquals(ctx_.base_lexicalScope().base_super(), evalAndReturn("super")); 177 } 178 179 public void testSelection() throws InterpreterException { 180 // def x := object: { def y() { 3 } } 181 NATObject x = new NATObject(ctx_.base_self()); 182 NATMethod y = new NATMethod(atY_, NATTable.EMPTY, new AGBegin(NATTable.atValue(new ATObject[] { atThree_ }))); 183 x.meta_addMethod(y); 184 ctx_.base_lexicalScope().meta_defineField(atX_, x); 185 186 assertEquals(evalAndReturn("x.&y").asClosure().base_method(), y); 187 } 188 189 public void testFirstClassMessage() throws InterpreterException { 190 ATMessage methInv = evalAndReturn(".m(3)").asMessage(); 191 192 assertEquals(atM_, methInv.base_selector()); 193 assertEquals(atThree_, methInv.base_arguments().base_at(NATNumber.ONE)); 194 assertTrue(methInv instanceof ATMethodInvocation); 195 } 196 197 public void testFirstClassAsyncMessage() throws Exception { 198 ATMessage asyncMsg = evalAndReturn("<-m(3)").asMessage(); 199 200 assertEquals(atM_, asyncMsg.base_selector()); 201 assertEquals(atThree_, asyncMsg.base_arguments().base_at(NATNumber.ONE)); 202 assertTrue(asyncMsg instanceof ATAsyncMessage); 203 // following is removed because async msges no longer encapsulate their receiver 204 // assertEquals(OBJNil._INSTANCE_, ((ATAsyncMessage) asyncMsg).base_receiver()); 205 } 206 207 public void testMethodApplication() throws InterpreterException { 208 // def x := 3 209 ctx_.base_lexicalScope().meta_defineField(atX_, atThree_); 210 211 // def identity(x) { x } 212 ATSymbol identityS = AGSymbol.alloc(NATText.atValue("identity")); 213 ATTable pars = NATTable.atValue(new ATObject[] { atX_ }); 214 NATMethod identity = new NATMethod(identityS, pars, new AGBegin(NATTable.atValue(new ATObject[] { atX_ }))); 215 ctx_.base_lexicalScope().meta_addMethod(identity); 216 217 evalAndCompareTo("identity(1)", NATNumber.ONE); 218 } 219 220 public void testClosureApplication() throws InterpreterException { 221 // def x := 3 222 ctx_.base_lexicalScope().meta_defineField(atX_, atThree_); 223 224 // def identity := { | x | x } 225 ATSymbol identityS = AGSymbol.alloc(NATText.atValue("identity")); 226 ATTable pars = NATTable.atValue(new ATObject[] { atX_ }); 227 NATClosure identity = new NATClosure(new NATMethod(identityS, pars, new AGBegin(NATTable.atValue(new ATObject[] { atX_ }))), ctx_); 228 ctx_.base_lexicalScope().meta_defineField(identityS, identity); 229 230 evalAndCompareTo("identity(1)", NATNumber.ONE); 231 } 232 233 public void testMethodInvocation() throws InterpreterException { 234 // def x := object: { def x := 3; def m(y) { y; x } } 235 NATObject x = new NATObject(ctx_.base_lexicalScope()); 236 NATMethod m = new NATMethod(atM_, NATTable.atValue(new ATObject[] { atY_ }), 237 new AGBegin(NATTable.atValue(new ATObject[] { atY_, atX_ }))); 238 x.meta_defineField(atX_, atThree_); 239 x.meta_addMethod(m); 240 ctx_.base_lexicalScope().meta_defineField(atX_, x); 241 242 evalAndCompareTo("x.m(1)", atThree_); 243 } 244 245 public void testDelegation() throws InterpreterException { 246 // def x := object: { def m() { self.y + 1 } } ; def y := 2 247 NATObject x = new NATObject(ctx_.base_lexicalScope()); 248 ATMethod m = evalAndReturn("def m() { self.y + 1 }").asClosure().base_method(); 249 x.meta_addMethod(m); 250 ctx_.base_self().meta_defineField(atY_, NATNumber.atValue(2)); 251 ctx_.base_lexicalScope().meta_defineField(atX_, x); 252 253 evalAndCompareTo("x^m()", atThree_); 254 } 255 256 public void testQuotation() throws InterpreterException { 257 evalAndCompareTo("`3", atThree_); 258 evalAndCompareTo("`x", atX_); 259 evalAndCompareTo("`(o.x)", "o.x"); 260 evalAndCompareTo("`(o.&x)", "o.&x"); 261 evalAndCompareTo("`{def x := 3}", "def x := 3"); 262 evalAndCompareTo("`{def x := `3}", "def x := `(3)"); 263 evalAndCompareTo("`{def x := #3}", "def x := 3"); 264 evalAndCompareTo("`{def foo(a) { #([1,2,3]) }}", "def foo(a) { [1, 2, 3] }"); 265 evalAndCompareTo("`{def foo(#@(`([a,b,c]))) { #@([1,2,3]) }}", "def foo(a, b, c) { 1; 2; 3 }"); 266 evalAndCompareTo("`{def foo: x bar: #@(`([y,z])) { 1 }}", "def foo:bar:(x, y, z) { 1 }"); 267 } 268 269 public void testArgumentSplicing() throws InterpreterException { 270 evalAndCompareTo("[1, @[2,[3]], [4], @[5], @[], 6]", "[1, 2, [3], [4], 5, 6]"); 271 272 // def m(x,y,z) { z } 273 NATMethod m = new NATMethod(atM_, NATTable.atValue(new ATObject[] { atX_, atY_, atZ_ }), 274 new AGBegin(NATTable.atValue(new ATObject[] { atZ_ }))); 275 ctx_.base_self().meta_addMethod(m); 276 277 evalAndCompareTo("m(1,@[2,3])", "3"); 278 evalAndCompareTo("self.m(1,@[2,3])", "3"); 279 } 280 281 public void testVariableArguments() throws InterpreterException { 282 // def m(x,y,@z) { [x, y, z] } 283 NATMethod m = new NATMethod(atM_, NATTable.atValue(new ATObject[] { atX_, atY_, new AGSplice(atZ_) }), 284 new AGBegin(NATTable.atValue(new ATObject[] { 285 NATTable.atValue(new ATObject[] { atX_, atY_, atZ_ }) 286 }))); 287 ctx_.base_self().meta_addMethod(m); 288 289 evalAndCompareTo("m(1,2,3,4,5)", "[1, 2, [3, 4, 5]]"); 290 evalAndCompareTo("m(1,2,3)", "[1, 2, [3]]"); 291 evalAndCompareTo("m(1,2)", "[1, 2, []]"); 292 evalAndCompareTo("m(1,2,@[3,4,5])", "[1, 2, [3, 4, 5]]"); 293 evalAndCompareTo("m(@[1,2,3])", "[1, 2, [3]]"); 294 } 295 296 public void testVariableKeywordArguments() throws InterpreterException { 297 // def foo:bar:(x,@y) { y } 298 NATMethod fooBar = new NATMethod(atFooBar_, NATTable.atValue(new ATObject[] { atX_, new AGSplice(atY_) }), 299 new AGBegin(NATTable.atValue(new ATObject[] { atY_ }))); 300 ctx_.base_self().meta_addMethod(fooBar); 301 302 evalAndCompareTo("foo: 1 bar: 2", "[2]"); 303 evalAndCompareTo("foo: 1 bar: @[2,3]", "[2, 3]"); 304 evalAndCompareTo("foo: 1 bar: @[2]", "[2]"); 305 evalAndCompareTo("foo: 1 bar: @[]", "[]"); 306 } 307 308 public void testVariableMultiDefinition() throws InterpreterException { 309 // def [x, @y ] := [1, 2, 3, @[4, 5] 310 // => x = 1; y = [2, 3, 4, 5] 311 evalAndCompareTo("def [x, @y ] := [1, 2, 3, @[4, 5]]", "[1, 2, 3, 4, 5]"); 312 assertEquals(NATNumber.ONE, ctx_.base_lexicalScope().impl_call(atX_, NATTable.EMPTY)); 313 assertEquals("[2, 3, 4, 5]", ctx_.base_lexicalScope().impl_call(atY_, NATTable.EMPTY).meta_print().javaValue); 314 } 315 316 /** test whether applying an empty closure {} yields nil */ 317 public void testEmptyClosureApplication() throws InterpreterException { 318 evalAndCompareTo("({})()", "nil"); 319 } 320 321}