Quellcode durchsuchen

Refactor standard libraries and add namespacing

Matt Coles vor 9 Jahren
Ursprung
Commit
d3a4826766
5 geänderte Dateien mit 83 neuen und 14 gelöschten Zeilen
  1. 22 6
      compiler.js
  2. 2 0
      example.mc
  3. 6 2
      fizzbuzz.mc
  4. 16 6
      stdlib.js
  5. 37 0
      lib/str.js

+ 22 - 6
compiler.js

81
       })
81
       })
82
       continue
82
       continue
83
     }
83
     }
84
-    let characters = /[a-zA-Z_]/
84
+    let characters = /[a-zA-Z_:]/
85
     if (characters.test(char)) {
85
     if (characters.test(char)) {
86
       let name = ''
86
       let name = ''
87
       while (characters.test(char)) {
87
       while (characters.test(char)) {
312
   switch (node.type) {
312
   switch (node.type) {
313
     case 'Prog':
313
     case 'Prog':
314
       let program = node.body.map(generator)
314
       let program = node.body.map(generator)
315
-      program.unshift('var _ = require("./stdlib.js")')
315
+      program.unshift('var _ = require("./lib/stdlib.js")(this)')
316
       return program.join('\n')
316
       return program.join('\n')
317
       break
317
       break
318
     case 'Statement':
318
     case 'Statement':
320
       break
320
       break
321
     case 'FunctionCall':
321
     case 'FunctionCall':
322
       if (!node.callee.name.match('(def|if|repeat)')) {
322
       if (!node.callee.name.match('(def|if|repeat)')) {
323
-        return (generator(node.callee) + '(' + node.args.map(generator).join(', ') + ')')
323
+        if (node.callee.name.match('include')) {
324
+          // Include is a special function and we will write the generation ourselves
325
+          if (node.args.length > 1) {
326
+            console.error("Compiler Error: (include) may only take 1 argument!")
327
+            process.exit(1)
328
+          } else {
329
+            let lib = './lib/' + node.args[0].value + '.js'
330
+            return ('var _' + node.args[0].value + ' = require("' + lib + '")(this)')
331
+          }
332
+        } else {
333
+          return (generator(node.callee) + '(' + node.args.map(generator).join(', ') + ')')
334
+        }
324
       } else {
335
       } else {
325
         return (generator(node.callee) + '(' + node.args.map((v, i) => {
336
         return (generator(node.callee) + '(' + node.args.map((v, i) => {
326
           if (i === 0) {
337
           if (i === 0) {
327
             return generator(v) + ', '
338
             return generator(v) + ', '
328
           } else {
339
           } else {
329
             if (i === 1) {
340
             if (i === 1) {
330
-              return 'function() {' + generator(v) + ';'
341
+              return 'function() { \n' + generator(v) + ';\n'
331
             } else {
342
             } else {
332
-              return generator(v) + '; '
343
+              return generator(v) + ';\n'
333
             }
344
             }
334
           }
345
           }
335
         }).join('') + '})')
346
         }).join('') + '})')
342
       return '}, function() {'
353
       return '}, function() {'
343
       break
354
       break
344
     case 'FunctionName':
355
     case 'FunctionName':
345
-      return '_.' + node.name
356
+      if (node.name.match("::")) {
357
+        let [namespace, func] = node.name.split("::")
358
+        return "_" + namespace + "." + func
359
+      } else {
360
+        return '_.' + node.name
361
+      }
346
       break
362
       break
347
     case 'VariableReference':
363
     case 'VariableReference':
348
       return '_.ref(\'' + node.value + '\')'
364
       return '_.ref(\'' + node.value + '\')'

+ 2 - 0
example.mc

1
 ; This is a test program
1
 ; This is a test program
2
+(include str)
2
 (assign twelve 12) ; This assigns the variable twelve, to the number literal 12
3
 (assign twelve 12) ; This assigns the variable twelve, to the number literal 12
3
 (assign myvar (add twelve (subtract 6 2))) ; This assigns the variable myvar, to the result of adding the variable twelve to the result of subtracting 2 from 6
4
 (assign myvar (add twelve (subtract 6 2))) ; This assigns the variable myvar, to the result of adding the variable twelve to the result of subtracting 2 from 6
4
 (log myvar) ; This logs the value of myvar
5
 (log myvar) ; This logs the value of myvar
32
 (log scopelol)
33
 (log scopelol)
33
 (repeat scopelol (log 10))
34
 (repeat scopelol (log 10))
34
 (if (eq 2 scopelol) (log "2 == scopelol") | (log "2 != scopelol"))
35
 (if (eq 2 scopelol) (log "2 == scopelol") | (log "2 != scopelol"))
36
+(log (str::concat "Hello " "World!"))

+ 6 - 2
fizzbuzz.mc

1
+(include str)
1
 (def fizzbuzz
2
 (def fizzbuzz
2
   (assign i 1)
3
   (assign i 1)
3
   (repeat $1
4
   (repeat $1
4
-    (if (eq (modulo i 3) 0) (if (eq (modulo i 5) 0) (log "FizzBuzz") | (log "Fizz")))
5
-    (if (eq (modulo i 5) 0) (log "Buzz") | (log i))
5
+    (assign result "")
6
+    (if (eq (modulo i 3) 0) (assign result (str::concat result "Fizz")))
7
+    (if (eq (modulo i 5) 0) (assign result (str::concat result "Buzz")))
8
+    (if (eq result "") (assign result i))
9
+    (log result)
6
     (assign i (add i 1))
10
     (assign i (add i 1))
7
   )
11
   )
8
 )
12
 )

+ 16 - 6
stdlib.js

36
     function_defs[prop.name] = body;
36
     function_defs[prop.name] = body;
37
   },
37
   },
38
   repeat: function (amount, body) {
38
   repeat: function (amount, body) {
39
-    for (i = 0 ; i < amount.value; i++) {
40
-        body() 
39
+    for (ii = 0 ; ii < amount.value; ii++) {
40
+        body.bind(_)() 
41
     }
41
     }
42
   },
42
   },
43
   eQ: function (arg1, arg2) {
43
   eQ: function (arg1, arg2) {
52
   },
52
   },
53
   if: function (pred, body_true, body_false) {
53
   if: function (pred, body_true, body_false) {
54
     if (pred.value) {
54
     if (pred.value) {
55
-      body_true()
55
+      body_true.bind(_)()
56
     } else {
56
     } else {
57
       if (body_false) {
57
       if (body_false) {
58
-        body_false()
58
+        body_false.bind(_)()
59
       }
59
       }
60
     }
60
     }
61
   },
61
   },
62
+  and: function (pred1, pred2) {
63
+    return pred1 && pred2
64
+  },
65
+  or: function (pred1, pred2) { 
66
+    return pred1 || pred2
67
+  },
62
   modulo: function (arg1, arg2) {
68
   modulo: function (arg1, arg2) {
63
     return {
69
     return {
64
       value: (arg1.value % arg2.value)
70
       value: (arg1.value % arg2.value)
88
   }
94
   }
89
 }
95
 }
90
 
96
 
91
-const _ = new Proxy({}, my_handler)
97
+const proxy_obj = new Proxy({}, my_handler)
98
+let _
92
 
99
 
93
-module.exports = _
100
+module.exports = function (self) {
101
+  _ = self
102
+  return proxy_obj
103
+}

+ 37 - 0
lib/str.js

1
+const global_obj = {}
2
+const function_defs = {}
3
+const warnings = {}
4
+const builtins = {
5
+  concat: function () {
6
+    let str = ""
7
+    for (i = 0; i < arguments.length; i++) {
8
+      str += arguments[i].value
9
+    }
10
+    return {
11
+      value: str
12
+    }
13
+  }
14
+}
15
+
16
+const my_handler = {
17
+  get: function (target, prop) {
18
+    let methods = Object.keys(builtins)
19
+    if (methods.includes(prop)) {
20
+      return builtins[prop]
21
+    } else {
22
+      console.error("Undefined function call! No such function: ", prop)
23
+    }
24
+  }, 
25
+  set: function (target, prop, data) {
26
+    if (prop === 'w') data.map((w) => warnings.w = true)
27
+    else console.error("Attempting to set unknown property on interpreter! How did you do that?")
28
+  }
29
+}
30
+
31
+const proxy_obj = new Proxy({}, my_handler)
32
+let _
33
+
34
+module.exports = function (self) {
35
+  _ = self
36
+  return proxy_obj
37
+}