Not logged in.  Login/Logout/Register | List snippets | | Create snippet | Upload image | Upload data

391
LINES

< > BotCompany Repo | #1035077 // test_leftArrowScript_classDefs (OK)

JavaX fragment (include) [tags: use-pretranspiled]

Transpiled version (37081L) is out of date.

set flag OurSyncCollections.

!include once #1034831 // Gazelle 22 Function Include for Testing

svoid test_leftArrowScript_classDefs() {
  temp LASMultiClassLoader cl = new(mc());
  test_leftArrowScript_classDefs(cl);
}

sclass test_leftArrowScript_classDefs_Base {
  S hey() { ret "ho"; }
}

svoid test_leftArrowScript_classDefs(LASMultiClassLoader cl) {
  var test = new TestFunctionValues<S, O>(l1 leftArrowVerbose);

  // define a class with two fields
  
  S classPrefix = "scriptClasses.";

  embedded O runScript(S code) {  
    new GazelleV_LeftArrowScriptParser parser;
    enableScaffolding(parser);
    parser.classDefPrefix(classPrefix);
    parser.lasClassLoader(cl);
    ret leftArrowVerbose(parser, code);
  }

  S classSrc = [[
    class MyClass {
      a: String
      b: String
    }
  ]], src = classSrc;

  Class c = cast runScript(src);
  assertStartsWith(print(c.getName()), classPrefix + "MyClass" + "_");
  
  // compile same source again - make sure we get the same class object
  assertSame(c, runScript(src));
  
  assertEqualsVerbose("Number of fields", 3, l(getDeclaredFields_cached(c)));
  assertEqualsVerbose("Type of a", S.class, getField(c, "a").getType());
  assertEqualsVerbose("Type of b", S.class, getField(c, "b").getType());
  
  // Make sure a change in the class definition gives us a new class name
  Class c2 = cast runScript([[
    class MyClass {
      a: String
      c: String
    }
  ]]);
  print(className(c2));
  assertNotSame(c, c2);
  
  // Make sure a change in the methods also gives us a new class name
  S classSrc2 = [[
    class MyClass {
      def bla { "x" }
    }
  ]];
  c = (Class) runScript(classSrc2);
  assertSame(c, runScript(classSrc2));
  c2 = (Class) runScript([[
    class MyClass {
      def bla { "y" }
    }
  ]]);
  assertNotSame(c, c2);
  
  // Now let's try and use a script-defined class
  
  src = classSrc + [[
    x <- new MyClass
    y <- new MyClass
    x a <- "yo"
    y a <- "oy"
    x a
  ]];
  
  assertEqualsVerbose("yo", runScript(src));
  
  // Using the class in a function
  
  src = classSrc + [[
    def bla {
      x <- new MyClass
      x a <- "yo"
      x a
    }
    bla
  ]];
  
  assertEqualsVerbose("yo", runScript(src));
  
  // Now for defining some methods (yay!)
  
  src = [[
    class MyClass2 {
      def method1 { "I'm here" }
      def method2 a { reversed a }
    }
    
    x <- new MyClass2
    pair (x method1) (x method2 "sey")
  ]];
  
  assertEqualsVerbose(pair("I'm here", "yes"), runScript(src));
  
  // accessing instance fields
  
  src = [[
    class MyClass3 {
      a: String
      
      def getA { this a } // requiring the this keyword for now
      def setA a { this a <- a }
      def aLength { (this a) length }
    }
    
    x <- new MyClass3
    x setA "abc"
    assertEquals (x aLength) 3
    x getA
  ]];
  
  assertEqualsVerbose("abc", runScript(src));

  // fully qualified type  
  classSrc = [[
    class MyClass4 {
      a: java.util.List
    }
  ]];

  c = (Class) runScript(classSrc);
  assertEqualsVerbose(fieldType(c, "a"), L.class);
  
  // type with type parameter
  classSrc = [[
    class MyClass5 {
      a: L<S>
    }
  ]];

  c = (Class) runScript(classSrc);
  assertEqualsVerbose("Raw type of L<S> field", fieldType(c, "a"), L.class);
  assertEqualsVerbose("Generic type of L<S> field", genericFieldType(c, "a"),
    new ParameterizedTypeImpl(null, L, S));
    
  // primitive type
  classSrc = [[
    class MyClass6 {
      x: int
    }
  ]];

  c = (Class) runScript(classSrc);
  assertEqualsVerbose(fieldType(c, "x"), int.class);
  
  classSrc = [[
    class ToString {
      def toString : S { "It's me, George!" }
    }
    new ToString
  ]];
  
  assertEqualsVerbose("It's me, George!", str(runScript(classSrc)));
  
  // primitive array
  classSrc = [[
    class MyClass7 {
      x: int[]
    }
  ]];

  c = (Class) runScript(classSrc);
  assertEqualsVerbose(fieldType(c, "x"), int[].class);

  // define class implementing interface
  
  classSrc =
    [[ class Bla is IF0 { def get { "hello" } }
       new Bla ]];
    
  IF0 f = cast runScript(classSrc);
  assertEqualsVerbose("hello", f!);
  
  // call function on class defined inline
  
  assertEqualsVerbose(Class.class, runScript([[
    _getClass2 class A { }
  ]]));
  
  // constructor

  assertEqualsVerbose(5, runScript([[
    class MyClass8 {
      x: int
      
      ctor { this x <- 5 }
    }
    
    new MyClass8, x
  ]]);
  
  // initialized field

  assertEqualsVerbose(7, runScript([[
    class MyClass9 {
      x: int <- 7
    }
    
    new MyClass9, x
  ]]);
  
  cl.rememberClassBytes(true);
  cl.onClassDefined(l1 disassembleClass);
  
  // define class with superclass
  
  classSrc = [[
    class A { def yo { "yay" } }
    class B extends A { def wow { joinWithSpace (this yo) "amazing!" } }
    new B, wow
  ]];
  
  assertEqualsVerbose("yay amazing!", runScript(classSrc));
    
  // define class with superclass from outside of script
  
  classSrc = [[
    class B extends test_leftArrowScript_classDefs_Base {
      def wow { joinWithSpace (this hey) (this hey) (this hey) } }
    new B, wow
  ]];
    
  assertEqualsVerbose("ho ho ho", runScript(classSrc));
  
  // initializer

  runScript([[
    class MyClass9 {
      x: int
      initializer { this x <- 5 }
    }
    
    assertEqualsVerbose 5 < new MyClass9, x
  ]]);
    
  runScript([[
    class MyClass10 {
      l: L <- new ArrayList
      initializer { this l, add "init" }
      ctor { this l, add "ctor" }
    }
    
    assertEqualsVerbose (ll "init" "ctor") < new MyClass10, l
  ]]);
  
  // TODO: Call superclass method (basically needs full method compilation)
  
  /*runScript([[
    class MyClassA {
      def x: S { "hello" }
    }
    
    class MyClassB extends MyClassA {
      def x: S { ret concat (super x) " world" }
    }
    
    assertEqualsVerbose "hello world" < new MyClassB, x
  ]]);*/
  
  // Reference own class name
  
  runScript([[
    class MyClassSelf {
      def me: MyClassSelf { this }
    }
  ]]);
  
  // Methods have proper argument types
  
  runScript([[
    class ArgTypes {
      def doIt (s: S) { "a string" }
      def doIt (s: O) { "not a string" }
    }
    
    assertEqualsVerbose "a string" < new ArgTypes, doIt "yo"
    assertEqualsVerbose "not a string" < new ArgTypes, doIt 123
  ]]);
  
  // Methods with primitive return type
  
  runScript([[
    class PrimReturn {
      def theNumber: int { 123 }
    }
    
    assertEqualsVerbose 123 < new PrimReturn, theNumber
    assertEqualsVerbose "int" < str < findMethod (new PrimReturn) "theNumber", getReturnType
  ]]);
  
  // settable fields
  
  runScript([[
    class Settable {
      settable x: int
      settable b: bool
      settable l: long
      settable d: double
      settable y: S
    }
    
    s <- new Settable, x 5, y "test", b true
    assertEqualsVerbose 5 < s x
    assertEqualsVerbose 5 < call s "x"
    assertEqualsVerbose "test" < s y
    assertEqualsVerbose "test" < call s "y"
    assertEqualsVerbose true < s b
  ]]);
  
  // settable field with initializer
  
  runScript([[
    class Settable {
      settable s: S <- "hello"
    }
    
    assertEqualsVerbose "hello" < new Settable, s
  ]]);
  
  // selfType as method return type
  
  runScript([[
    class SelfTypeTest {
      def me: selfType { this }
    }
    
    t <- new SelfTypeTest
    assertEqualsVerbose t < t me
  ]]);
  
  // void methods
  
  runScript([[
    class VoidMethodTest is Closeable {
      def close: void {}
    }
  ]]);
  
  // transient field
  
  O o = runScript([[
    class TransientTest {
      transient i: int
    }
    new TransientTest
  ]]);
  assertTrueVerbose("transient", isTransient(fieldObject(o, "i")));
  
  // LS as type
  
  o = runScript([[
    class LSTest {
      l: LS
    }
    new LSTest
  ]]);
  assertEqualsVerbose("java.util.List<java.lang.String>",
    str(genericFieldType(o, "l")));
    
  // Referring to a script-defined class as a Class
  
  o = runScript([[
    class MyClass {}
    MyClass
  ]]);
  assertContainsVerbose("MyClass", className((Class) o));
  
  // static field
  
  o = runScript([[
    class MyClass {
      static hello: S <- "world"
    }
  ]]);
  assertEqualsVerbose("world", get((Class) o, "hello"));
}

download  show line numbers  debug dex  old transpilations   

Travelled to 6 computer(s): bhatertpkbcr, ekrmjmnbrukm, elmgxqgtpvxh, mowyntqkapby, mqqgnosmbjvj, wnsclhtenguj

No comments. add comment

Snippet ID: #1035077
Snippet name: test_leftArrowScript_classDefs (OK)
Eternal ID of this version: #1035077/86
Text MD5: 63cf200439f165632fcba747d09ca9cf
Author: stefan
Category: javax / left arrow script
Type: JavaX fragment (include)
Public (visible to everyone): Yes
Archived (hidden from active list): No
Created/modified: 2023-04-29 23:36:14
Source code size: 8666 bytes / 391 lines
Pitched / IR pitched: No / No
Views / Downloads: 236 / 682
Version history: 85 change(s)
Referenced in: [show references]