Commits

Anonymous committed 66b4d26

Make `$` into a globally-accessible name for a store for builtins.

Comments (0)

Files changed (2)

 
 Operations are accomplished with certain built-in unsaturated stores.  For
 example, there is a store called `add`, which can be used for addition.  These
-built-in stores are globally available; they do not exist in any particular
-store themselves.  One uses the `$` prefix operator to access this global
-namespace.
+built-in stores are all located in the special store `$`, which is a Special
+Name which is magically available in every scope and which cannot be assigned
+to, but which can be modified.
 
-    | print $add
+    | print $.add
     = [result=0,x=?,y=?]
 
-    | $add.x := 3
-    | $add.y := 5
-    | print $add.result
-    | print $add
+    | a := {
+    |   print $.add
+    | }
+    = [result=0,x=?,y=?]
+
+    | $ := 4
+    ? Cannot assign to $
+
+    | $.foo := 4
+    | print string "ok"
+    = ok
+
+    | $.add.x := 3
+    | $.add.y := 5
+    | print $.add.result
+    | print $.add
     = 8
     = [x=3,y=5,result=8]
 
 be used again.  Typically you want to make a copy of the store first, and use
 that, leaving the built-in store unmodified.
 
-    | o1 := $add*
+    | o1 := $.add*
     | o1.x := 4
     | o1.y := 7
-    | o2 := $add*
+    | o2 := $.add*
     | o2.x := o1.result
     | o2.y := 9
     | print o2.result
     = 20
 
 Since Xoomonk is not a strictly minimalist language, there is a selection
-of built-in stores which provide useful operations: `$add`, `$sub`, `$mul`,
-`$div`, `$gt`, and `$not`.
+of built-in stores which provide useful operations: `$.add`, `$.sub`, `$.mul`,
+`$.div`, `$.gt`, and `$.not`.
 
-Decision-making is also accomplished with a built-in store, `if`.  This store
+Decision-making is also accomplished with a built-in store, `$.if`.  This store
 contains variables caled `cond`, `then`, and `else`.  `cond` should
 be an integer, and `then` and `else` should be unsaturated stores where `x` is
 unassigned.  When the first three are assigned values, if `cond` is nonzero,
 it is assigned to `x` in the `then` store; otherwise, if it is zero, it is
 assigned to `x` in the `else` store.
 
-    | o1 := $if*
+    | o1 := $.if*
     | o1.then := {
     |   y := x
     |   print string "condition is true"
     | o1.cond := 0
     = condition is false
 
-    | o1 := $if*
+    | o1 := $.if*
     | o1.then := {
     |   y := x
     |   print string "condition is true"
     | o1.cond := 1
     = condition is true
 
-Repetition is also accomplished with a built-in store, `loop`.  This store
+Repetition is also accomplished with a built-in store, `$.loop`.  This store
 contains an unassigned variable called `do`.  When it is assigned a value,
 assumed to be an unsaturated store, a copy of it is made.  The variable
 `x` inside that copy is assigned the value 0.  This is supposed to saturate
 it is nonzero, the process repeats, with another copy of the `do` store
 getting 0 assigned to its `x`, and so forth.
 
-    | l := $loop*
+    | l := $.loop*
     | counter := 5
     | l.do := {
     |   y := x
     |   print ^.counter
-    |   o := $sub*
+    |   o := $.sub*
     |   o.x := ^.counter
     |   o.y := 1
     |   ^.counter := o.result
     = 1
     = done!
 
-Because the `loop` construct will always execute the `do` store at least once
+Because the `$.loop` construct will always execute the `do` store at least once
 (even assuming its only unassigned variable is `x`), it acts like a so-called
-`repeat` loop.  It can be used in conjunction with `if` to simulate a
+`repeat` loop.  It can be used in conjunction with `$.if` to simulate a
 so-called `while` loop.  With this loop, the built-in operations provided,
 and variables which may contain unbounded integer values, Xoomonk should
 be uncontroversially Turing-complete.
 malingering stores can act as these constructs.
 
     | perimeter := {
-    |   o1 := $mul*
+    |   o1 := $.mul*
     |   o1.x := x
     |   o1.y := 2
-    |   o2 := $mul*
+    |   o2 := $.mul*
     |   o2.x := y
     |   o2.y := 2
-    |   o3 := $add*
+    |   o3 := $.add*
     |   o3.x := o1.result
     |   o3.y := o2.result
     |   result := o3.result
     Expr    ::= (Block | Ref | Const) ["*"].
     Block   ::= "{" { Stmt } "}".
     Ref     ::= Name {"." Name}.
-    Name    ::= "^" | "$" <alphanumeric> | <alphanumeric>.
+    Name    ::= "^" | "$" | <alphanumeric>.
     Const   ::= <integer-literal>.
 
 Discussion
 import sys
 
 
+DOLLAR_STORE = None
+
+
 class XoomonkError(ValueError):
     pass
 
         if self.scanner.consume("^"):
             return AST('Upvalue')
         elif self.scanner.consume("$"):
-            self.scanner.check_type("identifier")
-            id = self.scanner.token
-            self.scanner.scan()
-            return AST('Dollar', value=id)
+            return AST('Identifier', value='$')
         else:
             self.scanner.check_type("identifier")
             id = self.scanner.token
             i = 0
             while i <= num_children - 2:
                 name = ref.children[i].value
-                store_to_use = store_to_use[name]
+                if name == '$':
+                    store_to_use = DOLLAR_STORE
+                else:
+                    store_to_use = store_to_use[name]
                 i += 1
         name = ref.children[-1].value
+        if name == '$':
+            raise XoomonkError('Cannot assign to $')
         value = eval_xoomonk(ast.children[1], state)
         store_to_use[name] = value
         return value
             i = 0
             while i <= num_children - 2:
                 name = ast.children[i].value
-                store_to_use = store_to_use[name]
+                if name == '$':
+                    store_to_use = DOLLAR_STORE
+                else:
+                    store_to_use = store_to_use[name]
                 i += 1
         name = ast.children[-1].value
-        try:
-            return store_to_use[name]
-        except KeyError as e:
-            raise XoomonkError('Attempt to access undefined variable %s' % name)
+        if name == '$':
+            return DOLLAR_STORE
+        else:
+            try:
+                return store_to_use[name]
+            except KeyError as e:
+                raise XoomonkError('Attempt to access undefined variable %s' % name)
     elif type == 'IntLit':
         return ast.value
     elif type == 'CopyOf':
     return store
 
 
+def open_dollar_store():
+    global DOLLAR_STORE
+
+    def add(store):
+        store['result'] = store['x'] + store['y']
+        return store
+
+    def sub(store):
+        store['result'] = store['x'] - store['y']
+        return store
+
+    DOLLAR_STORE = {
+        'add': MalingeringStore(['x', 'y', 'result'], ['x', 'y'], add),
+        'sub': MalingeringStore(['x', 'y', 'result'], ['x', 'y'], sub),
+    }
+    
+
 def main(argv):
     optparser = OptionParser(__doc__)
     optparser.add_option("-a", "--show-ast",
     ast = p.program()
     if options.show_ast:
         print repr(ast)
+    open_dollar_store()
     try:
         result = eval_xoomonk(ast, {})
     except XoomonkError as e:
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.