Browse Source

Work on Raku. Transition to go-peg parser since that's much easier to use. Doesn't compile yet.

Beoran 6 years ago
parent
commit
bc80a5c499
4 changed files with 268 additions and 146 deletions
  1. 108 0
      raku/README
  2. 0 130
      raku/peg.go
  3. 0 16
      raku/raku.go
  4. 160 0
      raku/runtime.go

+ 108 - 0
raku/README

@@ -0,0 +1,108 @@
+RAKU is a scripting language that resembles Engish somewhat. 
+However it is a stealth lisp with smalltalk like semantics.
+
+In Lisp you would say (function1 arg1 (function2 arg2))
+In C you would write function1(arg1, function2(arg2));
+In Raku you will write function1 arg1 be function2 arg2 so
+
+
+attack the greater green gorgon with the large axe
+
+# Core problem: in most languages, arguments of a function are not only 
+# delimited, but also the start and end of the function call
+# are indicated somehow, so that calling several functions in one statement
+# is possible. Similarly for message passing.
+# C-like:
+# foo(a, b, c)
+# foo(a, bar(b , c) ,d ,e)
+# Lisp-like:
+# (foo a b c)
+# (foo a (bar b c) d e) 
+# What I'd like for Raku is drop the outer ()
+# foo a (bar b c) d e
+#  Here the newline at the end, or the . make is clear the statement is finished.
+# However, calling functions still requires a special delimiter. 
+# Unless if the parser knows that foo and bar are functions/methods/verbs.
+# Then it can distinguish between foo and bar and a b c d e. 
+# But then it still can't see where an inner call ends and the top level 
+# one begins: VERB NOUN PREP VERB NOUN PREP NOUN EOL -> 
+# is this VERB(NOUN , VERB(NOUN, NOUN)) or VERB(NOUN , VERB(NOUN), NOUN)?
+# Without an end-of call delimiter the parser cannot know.
+# For the simple case of VERB NOUN PERP NOUN EOL 
+# the EOL acts as the "end of call" marker, but it can't be used twice.
+#  
+# I checked Inform 7 but it's a huge language with many unnecessary 
+# complexities. It's simpler to solve the delimiter problem by using short words.
+# 
+# an as at ax be by do go if of in is it me no of or ox so to up us we
+# 
+# 
+# set foobar to be add 10 to 10 so
+# set foobar to tally add 10 to 10 end
+# for i from 0 to be size foo so then do
+# 
+# end
+# do / sub / block      ... so / end / done      -> block
+# be / run / call       ... so / end / done      -> sub-call, parenthesis 
+# list     / array      ... so / end / done      -> array/list value
+# act      / define WORD [NAME [PREP  NAME] BLOCK-> method definition on first NAME, which should be a type or instance. If none is given, "me" is used.
+# use NAME                                       -> variable declaration takes values of arguments give to block if any.
+# nil / nothing / none /                         -> nil value
+# true / false / yes / no                        -> boolean value
+# return                                         -> method return
+# yield                                          -> block return
+
+This is unambiguous in IO or Potion:
+
+OBJECT METHOD1(ARG1_1, ARG1_2, ...) METHOD2(ARG2_1, ...) METHOD3 EOL
+
+# Inversed, apart from the parameters this becomes: 
+METHOD3 METHOD2(ARG_2_1, ...) METHOD1(ARG1_1, ARG1_2, ....) OBJECT 
+# 
+# So io/potion ish 
+Bob name append(" and ", Jane name) println 
+# Would invert to
+println append(" and ", name Jane ) name Bob
+# now substitute the non-words with words
+println append of " and " with name Jane end name Bob
+# or if we use and for method chaining
+println and append " and " with name Jane and name Bob
+
+# So io/potion ish
+Bob hp decrease(Bob hp times(10) divide(Bob hpmax))  
+# Would invert to
+decrease(divide(hpmax Bob) times(10) hp Bob) hp Bob
+# now substitute the non-words with words
+decrease tally divide of hpmax Bob end times tally 10 end hp Bob end hp Bob
+# or if we use and for method chaining
+decrease tally divide tally hpmax Bob end and times tally 10 end and hp Bob end and hp Bob
+
+# Conclusion, mere complete inversion is undesirable because the sequence 
+# becomes unclear, what happens last is set first.
+# What is desirable is that like in English the verb comes before the object, 
+# but only once, UNLESS it's prettier after. So it's better to start out 
+# quasi-procedural 
+decrease(hp(Bob),  divide(times(hp(Bob), 10), hpmax(Bob)))  
+#
+decrease hp of Bob by call divide call multiply hp of Bob by 10 end with hpmax of Bob end
+# of course that sucks somewhat. Probably it would be split up.
+# but that's the pricve toi pay to keep thing sipmle. 
+# Requiring a call/end before most method/function calls resolves the 
+# bracketing problem, and allows multi-word names, without a symtab. 
+
+set newhp to hp of Bob
+multiply newhp by 10
+divide newhp by hpmax of Bob 
+
+# So, raku is a small english like language with an OOP like syntax, 
+# but no symtab lookup that happens only at runtime.  
+# The next question is then, how much syntax to provide.
+# Since, unlike TCL, I can't use pure string substitutons, some built in constructs are needed.
+# However, these can be limited to Smalltalk-level constructs. 
+# No if/while/etc is really needed, these can be methods in stead.
+
+
+
+
+
+

+ 0 - 130
raku/peg.go

@@ -88,136 +88,6 @@ func parseFile(filename string) (*Result, error) {
 }
 
 
-type Method func (raku * Raku, message string, target Object, args ... interface{}) (Object, error)
-
-type Command struct {
-    Name string
-    Method 
-}
-
-type CommandMap = map[string] Command
-
-type Class interface {
-    Object
-    Parent() * Class
-    Selector(name string) * Method
-}
-
-type Object interface {
-    Class() Class
-    Send(raku * Raku, message string, args ... interface {}) (Object, error)
-}
-
-var RootClass * DefaultClass = &DefaultClass{}
-
-type DefaultObject struct {
-    class Class
-    * Raku
-    CommandMap
-}
-
-func (object DefaultObject) Selector(name string) Method {
-    command, ok := object.CommandMap[name]
-    if !ok {
-        method := object.class.Selector(name)
-        if method == nil { 
-            return nil
-        }
-        return method
-    }
-    return command.Method
-}
-
-
-func (object DefaultObject) Class() Object {
-    return RootClass
-}
-
-const METHOD_MISSING = "method_missing"
-
-func (object DefaultObject) Send(raku * Raku, message string, args ... interface {}) (Object, error) {    
-    method := object.Selector(message)
-    if (method != nil) {
-        return method(object.Raku, message, object, args ...)
-    }
-    method = object.Selector(METHOD_MISSING)
-    if (method != nil) {
-        return method(object.Raku, message, object, args ...)
-    }
-    return nil, fmt.Errorf("Cannot send message %s to object %v.", message, object)
-}
-
-type DefaultClass struct {
-    parent * Class
-    DefaultObject
-}
-
-func (class DefaultClass) Parent() Object {
-    return class.parent
-}
-
-type NilClass struct {
-    DefaultClass
-}
-
-var Nil Object = &DefaultObject{NilClass};
-
-var Root * Object = &DefaultObject{RootClass}
-
-type Boolean struct {
-    DefaultObject
-}
-
-var True  * Boolean = &Boolean{Root}
-var False * Boolean = &Boolean{Root}
-
-
-func (boolean Boolean) Parent() Object {
-    return Nil
-}
-
-func (boolean Boolean) Send(raku * Raku, message string, args ... interface {}) (Object, error) {
-    return Root.Send(raku, message, args ...);
-}
-
-
-func (method Method) Parent() Object {
-    return Nil
-}
-
-func (method Method) Send(raku * Raku, message string, args ... interface {}) (Object, error) {
-    return method(raku, message, method, args...) 
-}
-
-
-
-
-type Raku struct {
-    * Parser
-    CommandMap
-    Root    * Object
-    Nil     * NilClass    
-    True    * Boolean
-    False   * Boolean
-
-}
-
-func New(peg_filename string) (*Raku, error) {
-    var err error
-    result := &Raku{}
-    result.Parser, err = LoadParser(peg_filename)
-    if (err == nil) {
-                
-    } 
-    return result, err
-}
-
-
-func Evaluate(raku * Raku, result Result) {
-    _
-}
-
-
 
 
 

+ 0 - 16
raku/raku.go

@@ -1033,22 +1033,6 @@ const (
     DefineTypeVar
 )
 
-type Value interface {
-}
-
-type StringValue string
-
-type SymbolValue string
-
-type IntegerValue int64
-
-type FloatValue float64
-
-type ArrayValue []Value
-
-type MapValue map[string]Value
-
-type BoolValue bool
 
 
 type Variable struct {

+ 160 - 0
raku/runtime.go

@@ -0,0 +1,160 @@
+package raku
+
+type Value interface {
+}
+
+type StringValue string
+
+type SymbolValue string
+
+type IntegerValue int64
+
+type FloatValue float64
+
+type ArrayValue []Value
+
+type MapValue map[string]Value
+
+type BoolValue bool
+
+/** An instance of a class. */
+type Instance interface {
+    Send Method
+}
+
+/** A class. */
+type Class interface {
+    Instance
+    
+}
+
+
+type Method func (raku * Raku, message string, target Object, args ... interface{}) (Object, error)
+
+type Command struct {
+    Name string
+    Method 
+}
+
+type CommandMap = map[string] Command
+
+type Class interface {
+    Object
+    Parent() * Class
+    Selector(name string) * Method
+}
+
+type Object interface {
+    Class() Class
+    Send(raku * Raku, message string, args ... interface {}) (Object, error)
+}
+
+var RootClass * DefaultClass = &DefaultClass{}
+
+type DefaultObject struct {
+    class Class
+    * Raku
+    CommandMap
+}
+
+func (object DefaultObject) Selector(name string) Method {
+    command, ok := object.CommandMap[name]
+    if !ok {
+        method := object.class.Selector(name)
+        if method == nil { 
+            return nil
+        }
+        return method
+    }
+    return command.Method
+}
+
+
+func (object DefaultObject) Class() Object {
+    return RootClass
+}
+
+const METHOD_MISSING = "method_missing"
+
+func (object DefaultObject) Send(raku * Raku, message string, args ... interface {}) (Object, error) {    
+    method := object.Selector(message)
+    if (method != nil) {
+        return method(object.Raku, message, object, args ...)
+    }
+    method = object.Selector(METHOD_MISSING)
+    if (method != nil) {
+        return method(object.Raku, message, object, args ...)
+    }
+    return nil, fmt.Errorf("Cannot send message %s to object %v.", message, object)
+}
+
+type DefaultClass struct {
+    parent * Class
+    DefaultObject
+}
+
+func (class DefaultClass) Parent() Object {
+    return class.parent
+}
+
+type NilClass struct {
+    DefaultClass
+}
+
+var Nil Object = &DefaultObject{NilClass};
+
+var Root * Object = &DefaultObject{RootClass}
+
+type Boolean struct {
+    DefaultObject
+}
+
+var True  * Boolean = &Boolean{Root}
+var False * Boolean = &Boolean{Root}
+
+
+func (boolean Boolean) Parent() Object {
+    return Nil
+}
+
+func (boolean Boolean) Send(raku * Raku, message string, args ... interface {}) (Object, error) {
+    return Root.Send(raku, message, args ...);
+}
+
+
+func (method Method) Parent() Object {
+    return Nil
+}
+
+func (method Method) Send(raku * Raku, message string, args ... interface {}) (Object, error) {
+    return method(raku, message, method, args...) 
+}
+
+
+type Raku struct {
+    * Parser
+    CommandMap
+    Root    * Object
+    Nil     * NilClass    
+    True    * Boolean
+    False   * Boolean
+
+}
+
+func New(peg_filename string) (*Raku, error) {
+    var err error
+    result := &Raku{}
+    result.Parser, err = LoadParser(peg_filename)
+    if (err == nil) {
+                
+    } 
+    return result, err
+}
+
+
+func Evaluate(raku * Raku, result Result) {
+    _
+}
+
+
+