From 36f065e88b28be534f351a4da7b4a79fdd048bed Mon Sep 17 00:00:00 2001 From: Vihan B Date: Sat, 26 Nov 2016 20:07:41 -0800 Subject: [PATCH] feature [dict]: Added eval_accessor to dicts, abandoned `repr` The `repr` operator was old, had weird support, and served with little purpose over `String::`. All items have now merged `repr` with `String::` and `repr` has been abandoned. `repr` can now be considered deprecated and will be removed in the next parser release. Signed-off-by: Vihan B --- package.json | 2 +- src/interpreter/core/consts/dict.es6 | 2 +- src/interpreter/core/env/defaults.es6 | 4 +- .../core/primitives/Dictionary.es6 | 42 ++++++++++++--- src/interpreter/core/primitives/String.es6 | 1 - .../core/primitives/cast/array.es6 | 7 +-- src/interpreter/core/primitives/cast/dict.es6 | 42 +++++++++++++++ .../core/primitives/cast/regex.es6 | 3 +- .../core/primitives/cast/string.es6 | 7 ++- src/interpreter/core/primitives/op/regex.es6 | 5 -- src/interpreter/core/primitives/op/string.es6 | 9 ---- src/stdlib/api.es6 | 2 + src/stdlib/stdlib.es6 | 1 + test/tests/Primitives/Op/Regex.js | 51 ------------------- test/tests/primitives/op/Regex.js | 16 +++--- vbump.sh | 2 +- 16 files changed, 101 insertions(+), 95 deletions(-) delete mode 100644 test/tests/Primitives/Op/Regex.js diff --git a/package.json b/package.json index a36fe29e..20278a7b 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,7 @@ "atob": "^2.0.3", "bases": "^0.2.1", "btoa": "^1.1.2", - "cheddar-parser": "~0.2.2", + "cheddar-parser": "~0.3.0", "colors": "^1.1.2", "commander": "^2.9.0", "crypto": "0.0.3", diff --git a/src/interpreter/core/consts/dict.es6 b/src/interpreter/core/consts/dict.es6 index ab4c6f7e..71e789f6 100644 --- a/src/interpreter/core/consts/dict.es6 +++ b/src/interpreter/core/consts/dict.es6 @@ -1 +1 @@ -export const KEY_INTERNAL = new Set("String", "Number"); +export const KEY_INTERNAL = new Set(["String", "Number"]); diff --git a/src/interpreter/core/env/defaults.es6 b/src/interpreter/core/env/defaults.es6 index 13fb7898..2b0b1160 100644 --- a/src/interpreter/core/env/defaults.es6 +++ b/src/interpreter/core/env/defaults.es6 @@ -11,12 +11,10 @@ export const DEFAULT_OP = new Map([ if (!LHS || !LHS.Cast) return CheddarError.NO_OP_BEHAVIOR; - // Attempt to call `repr`, else, cast to string + // get the string representation let VAL = LHS.constructor.Name === 'String' ? LHS : LHS.Cast.has('String') ? LHS.Cast.get('String')(LHS) - : LHS.Operator.has('repr') - ? LHS.Operator.get('repr')(null, LHS) : LHS; diff --git a/src/interpreter/core/primitives/Dictionary.es6 b/src/interpreter/core/primitives/Dictionary.es6 index f5b5cd07..5b63eee9 100644 --- a/src/interpreter/core/primitives/Dictionary.es6 +++ b/src/interpreter/core/primitives/Dictionary.es6 @@ -6,10 +6,19 @@ import { KEY_INTERNAL } from '../consts/dict'; import BehaviorOperator from './op/dict'; import BehaviorCast from './cast/dict'; +import NIL from '../consts/nil'; +import CheddarVariable from '../env/var'; + +import CheddarScope from '../env/scope'; + function evaluate(item, scope) { return new CheddarEval({ _Tokens: [item] }, scope).exec(); } +function toRepr(item) { + return KEY_INTERNAL.has(item.constructor.Name) ? item.value : item; +} + export default class CheddarDictionary extends CheddarClass { static Name = "Dictionary"; @@ -31,20 +40,39 @@ export default class CheddarDictionary extends CheddarClass { let tok_value = evaluate(entry[1], this.scope); - if (typeof tok_key === "string") { - return tok_key; + if (typeof tok_value === "string") { + return tok_value; } - if (KEY_INTERNAL.has(tok_key.constructor.Name)) { - this.value.set(tok_key.value, tok_value); - } else { - this.value.set(tok_key, tok_value); - } + this.value.set(toRepr(tok_key), tok_value); } + // evaluated accessor boilerplate + this.scope_ref = new CheddarScope(); + let scope_ref_setter = this.scope_ref.setter; + this.scope_ref.setter = (path, res) => { + this.value.set(path, res.Value); + scope_ref_setter.call(this.scope_ref, path, res); + }; + return true; } + eval_accessor(token) { + // Go ahead and grab token + let val = this.value.get(toRepr(token)); + + if (!val) return new CheddarVariable(new NIL); + + // Scope boilerplate + val.scope = this.scope_ref; + val.Reference = toRepr(token); + + this.scope_ref.setter(val.Reference, val = new CheddarVariable(val)); + + return val; + } + Operator = new Map([...CheddarClass.Operator, ...BehaviorOperator]); Cast = BehaviorCast; } diff --git a/src/interpreter/core/primitives/String.es6 b/src/interpreter/core/primitives/String.es6 index ba705ea2..51d5ffc9 100644 --- a/src/interpreter/core/primitives/String.es6 +++ b/src/interpreter/core/primitives/String.es6 @@ -30,7 +30,6 @@ export default class CheddarString extends CheddarClass { scope_ref_setter.call(this.scope_ref, path, res); }; - return true; } diff --git a/src/interpreter/core/primitives/cast/array.es6 b/src/interpreter/core/primitives/cast/array.es6 index 6f939c11..0a47e800 100644 --- a/src/interpreter/core/primitives/cast/array.es6 +++ b/src/interpreter/core/primitives/cast/array.es6 @@ -9,14 +9,11 @@ export default new Map([ Cast; for (let i = 0; i < self.value.length; i++) { Cast = self.value[i] && self.value[i].Cast ? - self.value[i].Cast.has('String') || - self.value[i].Operator.has('repr') : false; + self.value[i].Cast.has('String') : false; if (Cast) Stringified += (i ? ", " : "") + ( - self.value[i].Cast.has('String') ? - self.value[i].Cast.get('String')(self.value[i]) : - self.value[i].Operator.get('repr')(null, self.value[i]) + self.value[i].Cast.get('String')(self.value[i]) ).value; else Stringified += (i ? ", " : "") + `<${self.value[i].constructor.Name || self.value[i].Name}>`; diff --git a/src/interpreter/core/primitives/cast/dict.es6 b/src/interpreter/core/primitives/cast/dict.es6 index 575aef63..99773773 100644 --- a/src/interpreter/core/primitives/cast/dict.es6 +++ b/src/interpreter/core/primitives/cast/dict.es6 @@ -1,5 +1,47 @@ import CheddarString from '../String'; import HelperInit from '../../../../helpers/init'; +function padItem(str) { + let lines = str.split(/\r?\n/g); + if (lines.length < 2) return str; + + for (var i = 1; i < lines.length; i++) { + lines[i] = ' ' + lines[i]; + } + + return lines.join("\n"); +} + export default new Map([ + ['String', (self) => { + // Output strings without delimiter + var string = ""; + + // From each key, obtain the string representation of both sides + self.value.forEach((value, key) => { + let [k, v] = [key, value].map( + // Convert `item` to string representation + // pad with 4 spaces then + (item) => { + // Get the primitive value + let value; + if (typeof item !== 'object' && typeof item !== 'function') { + // Handle primitives + value = typeof item == 'string' ? JSON.stringify(item) : item; + } else { + value = item.Cast && item.Cast.has("String") ? item.Cast.get("String")(item).value : `<${item.Name || item.constructor.Name}>`; + } + + if (item instanceof self.constructor) return padItem(value); + else return value; + } + ); + + string += `\n ${k}: ${v}`; + }); + + if (!string) return HelperInit(CheddarString, "[:]"); + + return HelperInit(CheddarString, `[${string}\n]`); + }] ]); diff --git a/src/interpreter/core/primitives/cast/regex.es6 b/src/interpreter/core/primitives/cast/regex.es6 index 888e105f..28963589 100644 --- a/src/interpreter/core/primitives/cast/regex.es6 +++ b/src/interpreter/core/primitives/cast/regex.es6 @@ -6,7 +6,6 @@ import HelperInit from '../../../../helpers/init'; export default new Map([ ['String', (self) => { let CheddarString = require('../String'); - - return HelperInit(CheddarString, self.source); + return HelperInit(CheddarString, `/${self.value.xregexp.source}/${self.value.xregexp.flags}`); }] ]); diff --git a/src/interpreter/core/primitives/cast/string.es6 b/src/interpreter/core/primitives/cast/string.es6 index c6846f83..6e0d0a49 100644 --- a/src/interpreter/core/primitives/cast/string.es6 +++ b/src/interpreter/core/primitives/cast/string.es6 @@ -18,7 +18,12 @@ export default new Map([ return HelperInit(CheddarNumber, ...Attempt._Tokens); else return CheddarError.CAST_FAILED; - }] + }], + ['String', (self) => { + return HelperInit(self.constructor, '"' + self.value.replace( + /"|\\/g, "\\$&" + ) + '"'); + }], ]); /* diff --git a/src/interpreter/core/primitives/op/regex.es6 b/src/interpreter/core/primitives/op/regex.es6 index a96b6e99..bf70b078 100644 --- a/src/interpreter/core/primitives/op/regex.es6 +++ b/src/interpreter/core/primitives/op/regex.es6 @@ -2,11 +2,6 @@ import HelperInit from '../../../../helpers/init'; import XRegExp from 'xregexp'; export default new Map([ - ['repr', (LHS, RHS) => { - let CheddarString = require('../String'); - return HelperInit(CheddarString, `/${RHS.value.xregexp.source}/${RHS.value.xregexp.flags}`); - }], - ['|', (LHS, RHS) => { if (LHS && RHS instanceof LHS.constructor) { return HelperInit(LHS.constructor, XRegExp.union([LHS.value, RHS.value])); diff --git a/src/interpreter/core/primitives/op/string.es6 b/src/interpreter/core/primitives/op/string.es6 index ee154f58..30502ef2 100644 --- a/src/interpreter/core/primitives/op/string.es6 +++ b/src/interpreter/core/primitives/op/string.es6 @@ -6,15 +6,6 @@ import HelperInit from '../../../../helpers/init'; import sprintf from '../../../../stdlib/ns/IO/sprintf'; // == STRING == export default new Map([ - // Replace " with \" - // and replace \ - // with \\s - ['repr', (_, LHS) => { - return HelperInit(LHS.constructor, '"' + LHS.value.replace( - /"|\\/g, "\\$&" - ) + '"'); - }], - // String concatenation // using +, attempt to // implicitly cast diff --git a/src/stdlib/api.es6 b/src/stdlib/api.es6 index 7c63cde9..7a3f92dc 100644 --- a/src/stdlib/api.es6 +++ b/src/stdlib/api.es6 @@ -1,3 +1,4 @@ +import CheddarDictionary from '../interpreter/core/primitives/Dictionary'; import CheddarString from '../interpreter/core/primitives/String'; import CheddarSymbol from '../interpreter/core/primitives/Symbol'; import CheddarNumber from '../interpreter/core/primitives/Number'; @@ -16,6 +17,7 @@ import CheddarClass from '../interpreter/core/env/class'; import HelperInit from '../helpers/init'; var API = { + dictionary: CheddarDictionary, string: CheddarString, symbol: CheddarSymbol, number: CheddarNumber, diff --git a/src/stdlib/stdlib.es6 b/src/stdlib/stdlib.es6 index dbef86e3..d886c8cc 100644 --- a/src/stdlib/stdlib.es6 +++ b/src/stdlib/stdlib.es6 @@ -30,6 +30,7 @@ STDLIB.p("Symbol", API.symbol); STDLIB.p("Regex", API.regex); STDLIB.p("Number", API.number); STDLIB.p("Array", API.array); +STDLIB.p("Dictionary", API.dictionary); STDLIB.p("Boolean", API.bool); STDLIB.p("Function", API.func); diff --git a/test/tests/Primitives/Op/Regex.js b/test/tests/Primitives/Op/Regex.js deleted file mode 100644 index d9a32212..00000000 --- a/test/tests/Primitives/Op/Regex.js +++ /dev/null @@ -1,51 +0,0 @@ -var TestCheddarFrom = require('../../globals').TestCheddarFrom; -var chai = require('chai'); -var expect = chai.expect; -chai.should(); - -describe('Regex', function() { - describe('repr', function() { - it('should work', TestCheddarFrom.Code( - 'print repr /.+/', - '/.+/' - )) - - it('should work with transpiled items', TestCheddarFrom.Code( - 'print repr /(?b)/', - '/(?b)/' - )) - - it('should work with flags', TestCheddarFrom.Code( - 'print repr /(?b)/gi', - '/(?b)/gi' - )) - }) - - describe('|', function() { - it('should work', TestCheddarFrom.Code( - 'print repr ( /a/ | /b/ )', - '/a|b/' - )) - }) - - describe('+', function() { - it('should work', TestCheddarFrom.Code( - 'print repr ( /a/ + /b/ )', - '/ab/' - )) - }) - - describe('-', function() { - it('should work', TestCheddarFrom.Code( - 'print repr ( /a/ - /b/ )', - '/(?!b)(?:a)/' - )) - }) - - describe('*', function() { - it('should work', TestCheddarFrom.Code( - 'print repr ( /a/ * 3 )', - '/(?:a){3}/' - )) - }) -}); diff --git a/test/tests/primitives/op/Regex.js b/test/tests/primitives/op/Regex.js index d9a32212..0437c779 100644 --- a/test/tests/primitives/op/Regex.js +++ b/test/tests/primitives/op/Regex.js @@ -4,47 +4,47 @@ var expect = chai.expect; chai.should(); describe('Regex', function() { - describe('repr', function() { + describe('String::', function() { it('should work', TestCheddarFrom.Code( - 'print repr /.+/', + 'print String::/.+/', '/.+/' )) it('should work with transpiled items', TestCheddarFrom.Code( - 'print repr /(?b)/', + 'print String::/(?b)/', '/(?b)/' )) it('should work with flags', TestCheddarFrom.Code( - 'print repr /(?b)/gi', + 'print String::/(?b)/gi', '/(?b)/gi' )) }) describe('|', function() { it('should work', TestCheddarFrom.Code( - 'print repr ( /a/ | /b/ )', + 'print String::( /a/ | /b/ )', '/a|b/' )) }) describe('+', function() { it('should work', TestCheddarFrom.Code( - 'print repr ( /a/ + /b/ )', + 'print String::( /a/ + /b/ )', '/ab/' )) }) describe('-', function() { it('should work', TestCheddarFrom.Code( - 'print repr ( /a/ - /b/ )', + 'print String::( /a/ - /b/ )', '/(?!b)(?:a)/' )) }) describe('*', function() { it('should work', TestCheddarFrom.Code( - 'print repr ( /a/ * 3 )', + 'print String::( /a/ * 3 )', '/(?:a){3}/' )) }) diff --git a/vbump.sh b/vbump.sh index bc925485..11b8dd9c 100755 --- a/vbump.sh +++ b/vbump.sh @@ -56,7 +56,7 @@ echo; echo "Sucesfully prepared release" echo; -git tag -a "$VERSION" -m "$VERSION" +git tag -a "$VERSION" echo; echo "Created tag for ${bold}${VERSION}${normal}"