### Top-level elements * #include * #pragma * class * interface * pooldic ### Comments ``` #! comment text // comment text /* comment text */ ``` ### Literal notations * 200 decimal integer * 2r1100 binary integer * 16rFF00 hexadecimal integer * 20p9999.99 fixed-point decimal where 20 is the number of digits after the point * 999.9 fixed-point decimal * $X character * C'X' -> charcter?? * C"X" -> character?? * 'XXXX' string literal * "XXXX" string litearl with escaping * B'XXXXXX' -> byte array literal * B"XXXXX" -> byte array literal with escaping * #XXXX symbol * #'XXXX' quoted symbol * #"XXXX" quoted symbol with escaping * #\e123 Error literal * #\pB8000000 SmallPointer(smptr) literal * #() Array. Comma as element delimiter is optional * #[] ByteArray. Comma as element delimiter is optional #[ 16r10, 16r20, 16r30 ] #[ "\x10\x20", "\x30" ] * #{} Dictionary - not supported yet The followings are not literals. The followings forms expressions. * ##() Array expression. Comma required to delimit elements * ##[] ByteArray expression. Comma required to delimit elements * ##{} Dictionary expression. Comma required to delimit elements The followings are not implemented. but can i do something like these? * S#[] String literal with each character specified. S%{A B C '\n'} * S#{} String with dynamic expression * S#{ 65 asCharacter, 64 asCharacter } ### Class ``` class MyClass(Object) { method show: this { } } ``` Class attributes The word class can be followed by attribute list enclosed in parenthesis. e.g.) class(#limited,#immutable) * #limited - not instantiable with new. * #immutable - instantiated object to be read-only. * #final - disallow subclasses. * #uncopyable - instantiated object not to be copied. * #byte, #character, #halfword, #word, #liword, #pointer - specify the type of a non-pointer object. a non-pointer type can have an additional size enclosed in parenthesis. e.g.) #character(2) a non-pointer object is not allowed to have named instanced variables. a non-pointer object is always variable indexed. * #pointer - specify a pointer variable indexed object. an instantiate object can have extra object pointers in additon to named instance variables. ``` class(#word(2)) X(Object) { } X new -> create an object with 2 words. X new: 4 -> create an object with 6 words. ``` if an object is asked to instantiate with trailer in the class defintion, it becomes uncopyable, without the #uncopyable attribute. ``` class Shader(Object) from 'shader' { // if the shaer module calls moo_setclasstrsize(), an instance of Shader is uncopyable } ``` ### Pool dictionary ``` pooldic MyData { A := 20, B := 30, C := 40 } class MyClass(Object) { import MyData. method x () { MyData.A dump. C dump. // if imported, it doesn't require prefixing with MyData. } } class MyClass2(Object) { pooldic Const { A := 20, B := 30 } method x() { A dump. // the nested pooldic is auto-imported. Const.A dump. self.Const dump. } } class MyClass3(MyClass2) { pooldic Const { A := MyClass2.Const.A // pooldic is not inherited. need redefinition for auto-import B := MyClass2.Const.B } } class MyClass4(MyClass2) { import MyClass2.Const. // similar to redefinition inside the class. it won't be available MyClass4.Const as such is not available. method x { MyClass2.Const at: #XXX put: 'QQQQQQQQQQQQQQ'. // you can add a new item dynamically, (MyClass2.Const at: #XXX) dump. // and can access it. // the compiler doesn't recognize the dynamically added item as MyClass2.Const.XXX } } ``` ### Flow Control ``` k := if (i < 20) { 30 } else { 40 }. if (a < 10) { ... } elif (a < 20) { ... } else { ... }. ifnot (i < 20) { 30 } else { 40 }. /* TODO: ifnot or nif? elifnot or elnif? */ if (a < 10) { .. } elifnot (a > 20) { ... } else { ... }. ``` ``` while (true) { }. until (a > b) { }. do { } while (a > b). do { } until (a > b). [a > b] whileTrue: [ ... ]. [a > b] whileFalse: [ ... ]. ``` ``` 1 to: 20 do: [:count | ... ]. 1 to: 10 by: 3 do: [:count | ... ]. 30 timesRepeat: [ ... ]. ``` ### Exception handling Exception signal. Exception signal: "message". [ ... ] on: Exception do: [:ex | ... ]. ex retry. ex resume. ex resume: value. ex return: value. ### return from context(method/block) explicit return operators ``` ^ return_stacktop ^^ local_return ``` implicit return when the end of the context is reached * a method context returns the receiver. * a block context returns the last evaluated value. if nothing has been evaluated, nil is returned. ### goto ``` goto jump_label. jump_label: a + b. ``` goto inside a block context. ``` [ 1 + 2. goto r. 3 + 4. r: 99 ] ``` goto must not cross the boundary of the block context. ``` this is invalid. cannot jump into a block from outside and vice versa. goto x. [ x: 1 + 2 ]. ``` ### Type checking Type checking not implemented yet. ``` class SampleClass(Object) { method run => Integer { } method execute((Integer)a,(Integer)b) => Integer { } method handle: (Object)this with: (a Integer)care => Integer { } } ``` TODO: How to specify return type of a block? or How to specify parameter type to a block? How to evaluate a block type-safely? ``` [ :(Integer)a :(Integer)b => Integer | | (Integer)c (Integer)d } a + b ] with: 20 with: 10 the method value is a variadic method. and it is a primitive. [ :a :b | a + b ](1, 20) <---- syntax sugar for [:a :b | a + b] value(1, 20). [:(Integer)a :(Integer)b => Integer | a + b ] value("kkkk", 20) -> the first argument violates the expected type. -> argument types to a method is defined in the method signature. -> but the block argument types are specified in the block itself. -> so it doesn't seem natural to achieve type safety without treating 'value' specially. -> create a shorthand expression for 'value' [:(Integer)a :(Integer)b => (Integer) | a + b ](1, 2) -> ] followed by ( ===> shorthand expression for value. -> it looks more sensible to treat this () specially what looks better as a shorthand expression for block value? [ :a :b | a + b ](10, 20) [ 10 + 20 ]() // no arguments [ :a :b | a + b ]->(10, 20). // -> cannot form a valid binary selector. must exclude it from binary selector patterns [ 10 + 20 ]->() // if no arugments are required. continuation? | a | a->()? block value? | (Block)a | a->()? block value? ``` ### FFI ``` ffi := FFI new: 'libc.so.6'. [ (ffi call: #printf signature: 's|sl>i' arguments: #("[%s ffi test %ld]\n" "sloppy" 12345678)) dump. (ffi call: #printf signature: 's>i' arguments: #("[%% ffi test %%]\n")) dump. (ffi call: #puts signature: 's>i' arguments: #("this is ffi test")) dump. (ffi call: #time signature: 'p>l' arguments: #(#\p0)) dump. ] ensure: [ ffi close. ]. ``` ### Command line options ``` moo --log /dev/stderr ../kernel/test-001.moo moo --log /dev/stderr,warn+ ../kernel/test-001.moo ```