Просмотр исходного кода

Rework functions and add everything you need for a rudimentary FizzBuzz

Matt Coles лет назад: 9
Родитель
Сommit
f0c5fa2428
4 измененных файлов с 81 добавлено и 8 удалено
  1. 36 7
      compiler.js
  2. 4 0
      example.mc
  3. 10 0
      fizzbuzz.mc
  4. 31 1
      stdlib.js

+ 36 - 7
compiler.js

@@ -29,6 +29,14 @@ var tokenizer = function (input) {
29 29
       pos++
30 30
       continue
31 31
     }
32
+    if (char === '|') {
33
+      tokens.push({
34
+        type: 'bar',
35
+        value: char
36
+      })
37
+      pos++
38
+      continue
39
+    }
32 40
     let whitespace = /[;\s]/
33 41
     if (whitespace.test(char)) {
34 42
       if (char === ';') {
@@ -140,6 +148,14 @@ var parser = function (input) {
140 148
       }
141 149
     }
142 150
 
151
+    if (token.type === 'bar') {
152
+      pos++
153
+      return {
154
+        type: 'BarLiteral',
155
+        value: token.value
156
+      }
157
+    }
158
+
143 159
     if (token.type === 'string') {
144 160
       pos++
145 161
       return {
@@ -213,6 +229,8 @@ var traverser = function (ast, visitor) {
213 229
         break
214 230
       case 'DollarVar':
215 231
         break
232
+      case 'BarLiteral':
233
+        break
216 234
       default:
217 235
         throw {
218 236
           name: 'Compiler Error',
@@ -246,6 +264,12 @@ var transformer = function (ast) {
246 264
         value: node.value
247 265
       })
248 266
     },
267
+    BarLiteral: function (node, parent) {
268
+      parent._context.push({
269
+        type: 'BarLiteral',
270
+        value: node.value
271
+      })
272
+    },
249 273
     VariableReference: function (node, parent) {
250 274
       parent._context.push({
251 275
         type: 'VariableReference',
@@ -282,7 +306,7 @@ var transformer = function (ast) {
282 306
   return newAst
283 307
 }
284 308
 
285
-
309
+var escapeDepth = 0
286 310
 var generator = function (node) {
287 311
 
288 312
   switch (node.type) {
@@ -295,7 +319,7 @@ var generator = function (node) {
295 319
       return (generator(node.expr) + ';')
296 320
       break
297 321
     case 'FunctionCall':
298
-      if (node.callee.name !== 'def') {
322
+      if (!node.callee.name.match('(def|if|repeat)')) {
299 323
         return (generator(node.callee) + '(' + node.args.map(generator).join(', ') + ')')
300 324
       } else {
301 325
         return (generator(node.callee) + '(' + node.args.map((v, i) => {
@@ -303,22 +327,25 @@ var generator = function (node) {
303 327
             return generator(v) + ', '
304 328
           } else {
305 329
             if (i === 1) {
306
-              return "'" + generator(v) + '; '
330
+              return 'function() {' + generator(v) + ';'
307 331
             } else {
308 332
               return generator(v) + '; '
309 333
             }
310 334
           }
311
-        }).join('') + "')")
335
+        }).join('') + '})')
312 336
       }
313 337
       break;
314 338
     case 'DollarVar':
315
-      return '$' + node.value
339
+      return 'arguments[' + (+node.value-1) + ']'
340
+      break
341
+    case 'BarLiteral':
342
+      return '}, function() {'
316 343
       break
317 344
     case 'FunctionName':
318 345
       return '_.' + node.name
319 346
       break
320 347
     case 'VariableReference':
321
-      return '_.ref("' + node.value + '")'
348
+      return '_.ref(\'' + node.value + '\')'
322 349
       break
323 350
     case 'NumberLiteral':
324 351
       return '{value: ' + node.value + '}'
@@ -338,6 +365,8 @@ var generator = function (node) {
338 365
 
339 366
 
340 367
 // const myInput = '(assign twelve 12) (assign myvar (add twelve (subtract 6 2))) (log myvar)'
368
+const fileNameIn = process.argv[2]
369
+const fileNameOut = fileNameIn + '.js'
341 370
 const myInput = fs.readFileSync(process.argv[2], { encoding: 'utf-8' })
342 371
 const preProcessedInput = preprocess(myInput)
343 372
 const myTokens = tokenizer(preProcessedInput)
@@ -345,4 +374,4 @@ const parsedTree = parser(myTokens)
345 374
 const transformedTree = transformer(parsedTree)
346 375
 //console.log(JSON.stringify(transformedTree,null,2))
347 376
 const output = generator(transformedTree)
348
-fs.writeFileSync('output.js', output)
377
+fs.writeFileSync(fileNameOut, output)

+ 4 - 0
example.mc

@@ -28,3 +28,7 @@
28 28
 ngs without stupid escape 
29 29
 
30 30
 characters")
31
+(repeat 5 (log 10))
32
+(log scopelol)
33
+(repeat scopelol (log 10))
34
+(if (eq 2 scopelol) (log "2 == scopelol") | (log "2 != scopelol"))

+ 10 - 0
fizzbuzz.mc

@@ -0,0 +1,10 @@
1
+(def fizzbuzz
2
+  (assign i 1)
3
+  (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))
6
+    (assign i (add i 1))
7
+  )
8
+)
9
+
10
+(fizzbuzz 100)

+ 31 - 1
stdlib.js

@@ -34,6 +34,35 @@ const builtins = {
34 34
       console.warn("Warning! Redefining function, did you mean to do this?")
35 35
     }
36 36
     function_defs[prop.name] = body;
37
+  },
38
+  repeat: function (amount, body) {
39
+    for (i = 0 ; i < amount.value; i++) {
40
+        body() 
41
+    }
42
+  },
43
+  eQ: function (arg1, arg2) {
44
+    return {
45
+      value: arg1.value === arg2.value
46
+    }
47
+  },
48
+  eq: function (arg1, arg2) {
49
+    return {
50
+      value: arg1.value == arg2.value
51
+    }
52
+  },
53
+  if: function (pred, body_true, body_false) {
54
+    if (pred.value) {
55
+      body_true()
56
+    } else {
57
+      if (body_false) {
58
+        body_false()
59
+      }
60
+    }
61
+  },
62
+  modulo: function (arg1, arg2) {
63
+    return {
64
+      value: (arg1.value % arg2.value)
65
+    }
37 66
   }
38 67
 }
39 68
 
@@ -46,7 +75,8 @@ const my_handler = {
46 75
     } else {
47 76
       methods = Object.keys(function_defs)
48 77
       if (methods.includes(prop)) {
49
-        return (function () { eval(function_defs[prop].replace(/\$(\d+)/g, (m, n) => JSON.stringify(arguments[(+n-1)]))) })
78
+        //return (function () { eval(function_defs[prop].replace(/\$(\d+)/g, (m, n) => JSON.stringify(arguments[(+n-1)]))) })
79
+        return function_defs[prop]
50 80
       } else {
51 81
         console.error("Undefined function call! No such function: ", prop)
52 82
       }