diff --git a/.gitignore b/.gitignore index b512c09..884a4d8 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ -node_modules \ No newline at end of file +node_modules +out diff --git a/.npmignore b/.npmignore new file mode 100644 index 0000000..ff53e28 --- /dev/null +++ b/.npmignore @@ -0,0 +1,5 @@ +node_modules +src +test +.editorconfig +tsconfig.json \ No newline at end of file diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..ba8e41f --- /dev/null +++ b/.travis.yml @@ -0,0 +1,7 @@ +language: node_js +node_js: + - "16.2.0" +os: + - windows + - linux + - osx \ No newline at end of file diff --git a/Instance.js b/Instance.js deleted file mode 100644 index 8b9e282..0000000 --- a/Instance.js +++ /dev/null @@ -1,109 +0,0 @@ - -import Serializable from './Serializable.js'; -import minify from './minify.js'; -import debug from 'debug'; -import _ from 'lodash'; -const log = debug('vogue:instance'); - - -export default class Instance extends Serializable { - module = null; - links = {} - system = null; - context = null; - locals = []; - internalFunctions = {}; - - // reconstruct context when we need it... - createContext() { - let ctx = {}; - for(const name in this.links) { - ctx[name] = this.links[name]; - } - for(const name in this.module.imports) { - ctx[name] = this.module.imports[name]; - this.locals.push(name); - } - ctx = { - ...ctx, - ...this.system.staticInstances, - ...this.internalFunctions - } - for(const identifier in this.system.staticInstances) { - this.locals.push(identifier); - } - ctx.create = this.system.newInstance.bind(this.system); - this.locals.push('create'); - this.context = ctx; - }; - - ready = false; - - constructor(module, location, parameters, system) { - super(); - this.module = module; - this.location = location; - this.system = system; - for(const name of this.module.links.optional.arrays) this.links[name] = []; - for(const name of this.module.links.optional.single) this.links[name] = null; - - for(const fnName in this.module.functions) { - this.internalFunctions[fnName] = - this.invokeInternal.bind(this, fnName); - } - this.createContext(); - - this._link = new Proxy(this, { - get(target, prop, receiver) { - if(prop === 'restore') return undefined; - if(prop in target.module.functions) { - return target.invokeInternal.bind(target, prop); - } - return undefined; - } - }); - } - - hasPublicFunction(name) { - return (name in this.module.functions); - } - - invokeInternal(name, ...args) { - log('invoking', this.module.name.full + '.' + name, 'with args', args); - const content = this.module.functions[name].code; - const passingArguments = _.zipObject(this.module.functions[name].parameters, args); - if(!content) throw new TypeError(name + ' is not a function!'); - return evalInContext(content, this.context, this.locals, passingArguments); - } - - get link () { - return this._link; - } -} - -function evalInContext(js, context, locals, passingArguments) { - //# Return the results of the in-line anonymous function we .call with the passed context - // log('='.repeat(80) + 'OG Block'); - // log(js); - // log('='.repeat(80) + 'Arguments'); - // log(passingArguments); - const that = this; - return function() { - const preminJs = -`'use strict'; -(() => { - ${locals.map((k) => `const ${k} = this.${k};`).join('\n\t')} - ${Object.keys(passingArguments).map(name => `let ${name} = passingArguments.${name};`).join('\n\t')} - ${js} -})();`; - // log('='.repeat(80) + 'preminjs'); - // log(preminJs); - const newJs = minify(preminJs); - // log('='.repeat(80) + 'minjs'); - // log(newJs); - // newJs should inject into result... - let result; - eval(newJs); - return result; - }.call(context); -} \ No newline at end of file diff --git a/Module.js b/Module.js deleted file mode 100644 index ca08df7..0000000 --- a/Module.js +++ /dev/null @@ -1,101 +0,0 @@ -import createAst from './createAst.js' -import path from 'path'; -import debug from 'debug'; -import { createRequire } from 'module'; -import { pathToFileURL } from 'url'; -const log = debug('vogue:module'); - -export default class Module { - links = { - required: { - single: [], - arrays: [] - }, - optional: { - single: [], - arrays: [] - } - }; - globals = []; - functions = []; - identifiers = {}; - name = { - space: '', - last: '', - full: '' - }; - imports = {}; - variables = { - cold: [], - warm: [] - } - singleton = false; - keepalive = false; - 'static' = null; - - async directive({directive, value}) { - this[directive] = value ?? true; - } - - async link({required, array, name}) { - this.links - [required ? 'required' : 'optional'] - [array ? 'arrays' : 'single'] - .push(name); - } - - async namespace({namespace}) { - this.name.space = namespace; - this.name.full = this.name.space + '.' + this.name.last; - } - - async function({name, block, parameters}) { - this.functions[name] = { - code: block, - parameters - }; - } - - async import({importName, name}) { - const nodePath = path.resolve(this.rootDir, 'node_module'); - log('#'.repeat(80)); - log(nodePath); - const __require__ = createRequire(nodePath); - const imported = __require__(importName); - if('default' in imported) this.imports[name] = imported.default; - else this.imports[name] = imported; - } - - async variable({persist, name}) { - this.variables[persist ? 'cold' : 'warm'].push(name); - } - - static async create(location, rootDir) { - const module = new Module(); - const ast = createAst(location); - const name = path.parse(location).name; - - module.name.last = name; - module.name.full = name; - module.rootDir = rootDir; - - for (const item of ast) { - if ('name' in item) { - if(item.name in module.identifiers) - throw new Error('Identifier ' + item.name + ' already declared!'); - else module.identifiers[item.name] = item.type; - } - - if(item.type in module) { - await module[item.type](item); - } - } - - log('='.repeat(80)); - log(location); - log(module); - - return module; - } -} - diff --git a/examples/valyria/main.v b/examples/valyria/main.v new file mode 100644 index 0000000..c2e4461 --- /dev/null +++ b/examples/valyria/main.v @@ -0,0 +1,6 @@ +singleton; +link window + +restore { + window ??= create('SDL.window'); +} \ No newline at end of file diff --git a/examples/valyria/package.json b/examples/valyria/package.json new file mode 100644 index 0000000..0a233a9 --- /dev/null +++ b/examples/valyria/package.json @@ -0,0 +1,12 @@ +{ + "name": "valyria", + "version": "1.0.0", + "main": "index.js", + "license": "MIT", + "dependencies": { + "@kmamal/sdl": "^0.0.13", + "chalk": "^4.1.1", + "sisteransi": "^1.0.5", + "terminal-kit": "^2.1.2" + } +} diff --git a/examples/valyria/yarn.lock b/examples/valyria/yarn.lock new file mode 100644 index 0000000..e5e646d --- /dev/null +++ b/examples/valyria/yarn.lock @@ -0,0 +1,554 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@cronvel/get-pixels@^3.4.0": + version "3.4.0" + resolved "https://registry.yarnpkg.com/@cronvel/get-pixels/-/get-pixels-3.4.0.tgz#697cd691c16bbb8b29ed596da73fd6a7e9a2f34d" + dependencies: + jpeg-js "^0.4.1" + ndarray "^1.0.19" + ndarray-pack "^1.1.1" + node-bitmap "0.0.1" + omggif "^1.0.10" + pngjs "^5.0.0" + +"@kmamal/sdl@^0.0.13": + version "0.0.13" + resolved "https://registry.yarnpkg.com/@kmamal/sdl/-/sdl-0.0.13.tgz#20524ee00bc6fc427a2cc3c2d79ada1c34c7c338" + dependencies: + bindings "*" + prebuild-install "^6.0.1" + +ansi-regex@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" + +ansi-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" + +ansi-styles@^4.1.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" + dependencies: + color-convert "^2.0.1" + +aproba@^1.0.3: + version "1.2.0" + resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" + +are-we-there-yet@~1.1.2: + version "1.1.5" + resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz#4b35c2944f062a8bfcda66410760350fe9ddfc21" + dependencies: + delegates "^1.0.0" + readable-stream "^2.0.6" + +base64-js@^1.3.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" + +bindings@*: + version "1.5.0" + resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.5.0.tgz#10353c9e945334bc0511a6d90b38fbc7c9c504df" + dependencies: + file-uri-to-path "1.0.0" + +bl@^4.0.3: + version "4.1.0" + resolved "https://registry.yarnpkg.com/bl/-/bl-4.1.0.tgz#451535264182bec2fbbc83a62ab98cf11d9f7b3a" + dependencies: + buffer "^5.5.0" + inherits "^2.0.4" + readable-stream "^3.4.0" + +buffer@^5.5.0: + version "5.7.1" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" + dependencies: + base64-js "^1.3.1" + ieee754 "^1.1.13" + +chalk@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.1.tgz#c80b3fab28bf6371e6863325eee67e618b77e6ad" + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +chownr@^1.1.1: + version "1.1.4" + resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b" + +chroma-js@^2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/chroma-js/-/chroma-js-2.1.2.tgz#1075cb9ae25bcb2017c109394168b5cf3aa500ec" + dependencies: + cross-env "^6.0.3" + +code-point-at@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" + +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + dependencies: + color-name "~1.1.4" + +color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + +console-control-strings@^1.0.0, console-control-strings@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" + +core-util-is@~1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" + +cross-env@^6.0.3: + version "6.0.3" + resolved "https://registry.yarnpkg.com/cross-env/-/cross-env-6.0.3.tgz#4256b71e49b3a40637a0ce70768a6ef5c72ae941" + dependencies: + cross-spawn "^7.0.0" + +cross-spawn@^7.0.0: + version "7.0.3" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" + +cwise-compiler@^1.1.2: + version "1.1.3" + resolved "https://registry.yarnpkg.com/cwise-compiler/-/cwise-compiler-1.1.3.tgz#f4d667410e850d3a313a7d2db7b1e505bb034cc5" + dependencies: + uniq "^1.0.0" + +decompress-response@^4.2.0: + version "4.2.1" + resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-4.2.1.tgz#414023cc7a302da25ce2ec82d0d5238ccafd8986" + dependencies: + mimic-response "^2.0.0" + +deep-extend@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" + +delegates@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" + +detect-libc@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" + +end-of-stream@^1.1.0, end-of-stream@^1.4.1: + version "1.4.4" + resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" + dependencies: + once "^1.4.0" + +expand-template@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/expand-template/-/expand-template-2.0.3.tgz#6e14b3fcee0f3a6340ecb57d2e8918692052a47c" + +file-uri-to-path@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd" + +fs-constants@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad" + +gauge@~2.7.3: + version "2.7.4" + resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" + dependencies: + aproba "^1.0.3" + console-control-strings "^1.0.0" + has-unicode "^2.0.0" + object-assign "^4.1.0" + signal-exit "^3.0.0" + string-width "^1.0.1" + strip-ansi "^3.0.1" + wide-align "^1.1.0" + +github-from-package@0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/github-from-package/-/github-from-package-0.0.0.tgz#97fb5d96bfde8973313f20e8288ef9a167fa64ce" + +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + +has-unicode@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" + +ieee754@^1.1.13: + version "1.2.1" + resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" + +inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.3: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + +ini@~1.3.0: + version "1.3.8" + resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" + +iota-array@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/iota-array/-/iota-array-1.0.0.tgz#81ef57fe5d05814cd58c2483632a99c30a0e8087" + +is-buffer@^1.0.2: + version "1.1.6" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" + +is-fullwidth-code-point@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" + dependencies: + number-is-nan "^1.0.0" + +is-fullwidth-code-point@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" + +isarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + +jpeg-js@^0.4.1: + version "0.4.3" + resolved "https://registry.yarnpkg.com/jpeg-js/-/jpeg-js-0.4.3.tgz#6158e09f1983ad773813704be80680550eff977b" + +lazyness@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/lazyness/-/lazyness-1.2.0.tgz#5dc0f02c37280436b21f0e4918ce6e72a109c657" + +mimic-response@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-2.1.0.tgz#d13763d35f613d09ec37ebb30bac0469c0ee8f43" + +minimist@^1.2.0, minimist@^1.2.3: + version "1.2.5" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" + +mkdirp-classic@^0.5.2, mkdirp-classic@^0.5.3: + version "0.5.3" + resolved "https://registry.yarnpkg.com/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz#fa10c9115cc6d8865be221ba47ee9bed78601113" + +napi-build-utils@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/napi-build-utils/-/napi-build-utils-1.0.2.tgz#b1fddc0b2c46e380a0b7a76f984dd47c41a13806" + +ndarray-pack@^1.1.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/ndarray-pack/-/ndarray-pack-1.2.1.tgz#8caebeaaa24d5ecf70ff86020637977da8ee585a" + dependencies: + cwise-compiler "^1.1.2" + ndarray "^1.0.13" + +ndarray@^1.0.13, ndarray@^1.0.19: + version "1.0.19" + resolved "https://registry.yarnpkg.com/ndarray/-/ndarray-1.0.19.tgz#6785b5f5dfa58b83e31ae5b2a058cfd1ab3f694e" + dependencies: + iota-array "^1.0.0" + is-buffer "^1.0.2" + +nextgen-events@^1.3.4: + version "1.4.0" + resolved "https://registry.yarnpkg.com/nextgen-events/-/nextgen-events-1.4.0.tgz#82e7201e4d8421f1cb4dcfce973c10b455fdc2be" + +node-abi@^2.21.0: + version "2.26.0" + resolved "https://registry.yarnpkg.com/node-abi/-/node-abi-2.26.0.tgz#355d5d4bc603e856f74197adbf3f5117a396ba40" + dependencies: + semver "^5.4.1" + +node-bitmap@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/node-bitmap/-/node-bitmap-0.0.1.tgz#180eac7003e0c707618ef31368f62f84b2a69091" + +noop-logger@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/noop-logger/-/noop-logger-0.1.1.tgz#94a2b1633c4f1317553007d8966fd0e841b6a4c2" + +npmlog@^4.0.1: + version "4.1.2" + resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" + dependencies: + are-we-there-yet "~1.1.2" + console-control-strings "~1.1.0" + gauge "~2.7.3" + set-blocking "~2.0.0" + +number-is-nan@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" + +object-assign@^4.1.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + +omggif@^1.0.10: + version "1.0.10" + resolved "https://registry.yarnpkg.com/omggif/-/omggif-1.0.10.tgz#ddaaf90d4a42f532e9e7cb3a95ecdd47f17c7b19" + +once@^1.3.1, once@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + dependencies: + wrappy "1" + +path-key@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" + +pngjs@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/pngjs/-/pngjs-5.0.0.tgz#e79dd2b215767fd9c04561c01236df960bce7fbb" + +prebuild-install@^6.0.1: + version "6.1.2" + resolved "https://registry.yarnpkg.com/prebuild-install/-/prebuild-install-6.1.2.tgz#6ce5fc5978feba5d3cbffedca0682b136a0b5bff" + dependencies: + detect-libc "^1.0.3" + expand-template "^2.0.3" + github-from-package "0.0.0" + minimist "^1.2.3" + mkdirp-classic "^0.5.3" + napi-build-utils "^1.0.1" + node-abi "^2.21.0" + noop-logger "^0.1.1" + npmlog "^4.0.1" + pump "^3.0.0" + rc "^1.2.7" + simple-get "^3.0.3" + tar-fs "^2.0.0" + tunnel-agent "^0.6.0" + +process-nextick-args@~2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" + +pump@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" + dependencies: + end-of-stream "^1.1.0" + once "^1.3.1" + +rc@^1.2.7: + version "1.2.8" + resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" + dependencies: + deep-extend "^0.6.0" + ini "~1.3.0" + minimist "^1.2.0" + strip-json-comments "~2.0.1" + +readable-stream@^2.0.6: + version "2.3.7" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.3" + isarray "~1.0.0" + process-nextick-args "~2.0.0" + safe-buffer "~5.1.1" + string_decoder "~1.1.1" + util-deprecate "~1.0.1" + +readable-stream@^3.1.1, readable-stream@^3.4.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" + dependencies: + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" + +safe-buffer@^5.0.1, safe-buffer@~5.2.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + +safe-buffer@~5.1.0, safe-buffer@~5.1.1: + version "5.1.2" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + +semver@^5.4.1: + version "5.7.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" + +set-blocking@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" + +setimmediate@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" + +seventh@^0.7.40: + version "0.7.40" + resolved "https://registry.yarnpkg.com/seventh/-/seventh-0.7.40.tgz#a5a010496cb84421bb81f524840484a5aa473be9" + dependencies: + setimmediate "^1.0.5" + +shebang-command@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" + dependencies: + shebang-regex "^3.0.0" + +shebang-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" + +signal-exit@^3.0.0: + version "3.0.3" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c" + +simple-concat@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/simple-concat/-/simple-concat-1.0.1.tgz#f46976082ba35c2263f1c8ab5edfe26c41c9552f" + +simple-get@^3.0.3: + version "3.1.0" + resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-3.1.0.tgz#b45be062435e50d159540b576202ceec40b9c6b3" + dependencies: + decompress-response "^4.2.0" + once "^1.3.1" + simple-concat "^1.0.0" + +sisteransi@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed" + +string-kit@^0.12.5: + version "0.12.5" + resolved "https://registry.yarnpkg.com/string-kit/-/string-kit-0.12.5.tgz#e7f646e7740e54b7ecae6cf67b73bb616aa16652" + +string-width@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" + dependencies: + code-point-at "^1.0.0" + is-fullwidth-code-point "^1.0.0" + strip-ansi "^3.0.0" + +"string-width@^1.0.2 || 2": + version "2.1.1" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" + dependencies: + is-fullwidth-code-point "^2.0.0" + strip-ansi "^4.0.0" + +string_decoder@^1.1.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" + dependencies: + safe-buffer "~5.2.0" + +string_decoder@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" + dependencies: + safe-buffer "~5.1.0" + +strip-ansi@^3.0.0, strip-ansi@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" + dependencies: + ansi-regex "^2.0.0" + +strip-ansi@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" + dependencies: + ansi-regex "^3.0.0" + +strip-json-comments@~2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" + +supports-color@^7.1.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" + dependencies: + has-flag "^4.0.0" + +tar-fs@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-2.1.1.tgz#489a15ab85f1f0befabb370b7de4f9eb5cbe8784" + dependencies: + chownr "^1.1.1" + mkdirp-classic "^0.5.2" + pump "^3.0.0" + tar-stream "^2.1.4" + +tar-stream@^2.1.4: + version "2.2.0" + resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-2.2.0.tgz#acad84c284136b060dc3faa64474aa9aebd77287" + dependencies: + bl "^4.0.3" + end-of-stream "^1.4.1" + fs-constants "^1.0.0" + inherits "^2.0.3" + readable-stream "^3.1.1" + +terminal-kit@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/terminal-kit/-/terminal-kit-2.1.2.tgz#08689ff9f8efc6614d34d4cc7be916a91742b896" + dependencies: + "@cronvel/get-pixels" "^3.4.0" + chroma-js "^2.1.1" + lazyness "^1.2.0" + ndarray "^1.0.19" + nextgen-events "^1.3.4" + seventh "^0.7.40" + string-kit "^0.12.5" + tree-kit "^0.7.0" + +tree-kit@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/tree-kit/-/tree-kit-0.7.0.tgz#f677b10f79d9b4442ba20e0d87c8a12ecabe5fbb" + +tunnel-agent@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" + dependencies: + safe-buffer "^5.0.1" + +uniq@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/uniq/-/uniq-1.0.1.tgz#b31c5ae8254844a3a8281541ce2b04b865a734ff" + +util-deprecate@^1.0.1, util-deprecate@~1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + +which@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + dependencies: + isexe "^2.0.0" + +wide-align@^1.1.0: + version "1.1.3" + resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" + dependencies: + string-width "^1.0.2 || 2" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" diff --git a/grammar.ne b/lib/grammar.ne similarity index 81% rename from grammar.ne rename to lib/grammar.ne index ba7cfdb..2b93d0a 100644 --- a/grammar.ne +++ b/lib/grammar.ne @@ -13,11 +13,11 @@ STATEMENT -> _ LINK_DECLARATION EOL {% ([,stuff]) => { return stuff } %} IMPORT_STATMENT -> %IMPORT __ STRING __ %AS __ IDENTIFIER {% ([,,moduleName,,,,identifier]) => { return { type: 'import', name: identifier, importName: moduleName }} %} | %IMPORT __ IDENTIFIER __ %FROM __ STRING {% ([,,identifier,,,,moduleName]) => { return { type: 'import', name: identifier, importName: moduleName }} %} -FUNCTION_DECLARATION -> _ IDENTIFIER _ PARAMETERS:? _ JS_BLOCK EOL {% ([,name,,params,,block]) => { return { type: 'function', name: name, block, parameters: params } } %} - | _ %ASYNC __ IDENTIFIER _ PARAMETERS:? _ JS_BLOCK_ASYNC EOL {% ([,,,name,,params,,block]) => { return { type: 'function', name: name, block, parameters: params } } %} +FUNCTION_DECLARATION -> _ IDENTIFIER _ PARAMETERS:? _ JS_BLOCK EOL {% ([,name,,params,,block]) => { return { type: 'function', name: name, block, parameters: params ?? [], async: false } } %} + | _ %ASYNC __ IDENTIFIER _ PARAMETERS:? _ JS_BLOCK_ASYNC EOL {% ([,,,name,,params,,block]) => { return { type: 'function', name: name, block, parameters: params ?? [], async: true } } %} DIRECTIVE_STATEMENT -> DIRECTIVE __ IDENTIFIER EOL {% ([directive,,identifier]) => { return { type: 'directive', directive, value: identifier }} %} - | DIRECTIVE EOL {% ([directive]) => { return { type: 'directive', directive }} %} + | DIRECTIVE EOL {% ([directive]) => { return { type: 'directive', directive, value: true }} %} DIRECTIVE -> %SINGLETON {% () => 'singleton' %} | %KEEPALIVE {% () => 'keepalive' %} @@ -42,10 +42,10 @@ EOL -> _ %SEMICOLON:? STRING -> %STRING {% ([d]) => d.value.substring(1, d.value.length - 1) %} SEMICOLON -> %SEMICOLON IDENTIFIER -> %IDENTIFIER {% ([id]) => id.value %} -JS_BLOCK -> %JS_BLOCK {% ([block]) => minify(`result = (() => {${block.value.substring(2, block.value.length - 2)}})();`) %} - | %JS_BLOCK2 {% ([block]) => minify(`result = (() => {${block.value.substring(1, block.value.length - 1)}})();`) %} -JS_BLOCK_ASYNC -> %JS_BLOCK {% ([block]) => minify(`result = (async () => {${block.value.substring(2, block.value.length - 2)}})();`) %} - | %JS_BLOCK2 {% ([block]) => minify(`result = (async () => {${block.value.substring(1, block.value.length - 1)}})();`) %} +JS_BLOCK -> %JS_BLOCK {% ([block]) => (`{${block.value.substring(2, block.value.length - 2)}}`) %} + | %JS_BLOCK2 {% ([block]) => (`{${block.value.substring(1, block.value.length - 1)}}`) %} +JS_BLOCK_ASYNC -> %JS_BLOCK {% ([block]) => (`{${block.value.substring(2, block.value.length - 2)}}`) %} + | %JS_BLOCK2 {% ([block]) => (`{${block.value.substring(1, block.value.length - 1)}}`) %} SPREAD_OPERATOR -> %SPREAD_OPERATOR _ -> null | %SPACE {% () => undefined %} __ -> %SPACE {% () => undefined %} \ No newline at end of file diff --git a/lib/console.v b/lib/vogue/console.v similarity index 82% rename from lib/console.v rename to lib/vogue/console.v index 6f428e2..8ea7c01 100644 --- a/lib/console.v +++ b/lib/vogue/console.v @@ -3,6 +3,10 @@ static console; import chalk from 'chalk'; import tk from 'terminal-kit'; import ansi from 'sisteransi'; +import debugFactory from 'debug'; +import util from 'util'; + +runtime member debug; restore { const {terminal} = tk; @@ -11,12 +15,16 @@ restore { process.exit(2); } }); + + debug ??= debugFactory('vogue:console'); this.write(ansi.cursor.hide); + debug('Booted console plugin!'); } log(a) { if(typeof a === 'number') a = chalk.yellow(a); + if(typeof a === 'object') a = util.formatWithOptions({ colors: true }, '%o', a) // const string = a.toString(); diff --git a/package.json b/package.json index 4f9dd4f..3eb38b9 100644 --- a/package.json +++ b/package.json @@ -5,21 +5,31 @@ "license": "MIT", "type": "module", "bin": { - "vogue": "run.js" + "vogue": "out/run.js" }, "scripts": { - "c": "nearleyc", - "test": "node run.js test", + "test": "node --enable-source-maps --unhandled-rejections=strict out/run.js test", "debug": "cross-env DEBUG=vogue:* yarn test", - "postinstall": "cd test && yarn" + "debug:watch": "cross-env DEBUG=vogue:* supervisor -w out,test,lib -n exit --exec yarn -- test", + "postinstall": "yarn compile && cd test && yarn", + "postcompile:watch": "echo DONE", + "compile": "tsc", + "compile:watch": "tsc --watch" }, "dependencies": { + "@types/debug": "^4.1.5", + "@types/lodash": "^4.14.169", + "@types/nearley": "^2.11.1", + "@types/node": "^15.3.0", + "@types/uglify-js": "^3.13.0", "cross-env": "^7.0.3", "debug": "^4.3.1", "lodash": "^4.17.21", "moo": "^0.5.1", "nearley": "^2.20.1", "nedb": "^1.8.0", + "supervisor": "^0.12.0", + "typescript": "^4.2.4", "uglify-js": "^3.13.5", "yarn": "^1.22.10" } diff --git a/src/Instance.ts b/src/Instance.ts new file mode 100644 index 0000000..b9b5cb4 --- /dev/null +++ b/src/Instance.ts @@ -0,0 +1,96 @@ + +import Serializable from './Serializable.js'; +import minify from './minify.js'; +import debug from 'debug'; +import _ from 'lodash'; +const log = debug('vogue:instance'); +import vm from 'vm'; +import Module, { Link } from './Module.js'; +import System from './System.js'; +import { KV } from './KV.js'; +/** + * @typedef {import('./System.js').default} System + * @typedef {import('./Module.js').default} Module + */ + + +export default class Instance extends Serializable { + module: Module; + links = {} + system: System; + context: vm.Context; + locals = []; + internalFunctions = {}; + _link: Instance; + location: string; + + createContext(): vm.Context { + if(this.context) return this.context; + + const initialContext: KV = {}; + + // system globals! + // TODO turn this into its own vogue module! system.create/instance.create + // TODO request context from system... + initialContext.create = this.system.newInstance.bind(this.system); + initialContext.process = process; + for(const name in this.system.staticInstances) + initialContext[name] = this.system.staticInstances[name]; + + // local links! + // optional arrays + // TODO maybe make these property accessors to allow for some automation + for(const link of this.module.links.filter((v: Link) => v.array && !v.required)) + initialContext[link.name] = []; + for(const link of this.module.links.filter((v: Link) => !v.array && !v.required)) + initialContext[link.name] = null; + for(const variable of this.module.variables) + initialContext[variable.name] = null; + for(const name in this.module.imports) + initialContext[name] = this.module.imports[name]; + + const context = vm.createContext(initialContext); + + for(const name in this.module.functions) { + const { code, parameters, async } = this.module.functions[name]; + const injectedScript = +` +var ${name} = ${async ? 'async' : ''} function ${name}(${parameters.join(', ')}) ${code} +`; + vm.runInContext(injectedScript, context, { + + }); + } + + return context; + }; + + constructor(module: Module, location: string, parameters: {[name: string]: any}, system: System) { + super(); + this.module = module; + this.location = location; + this.system = system; + this.context = this.createContext(); + + this._link = new Proxy(this, { + get(target: Instance, prop: string, receiver) { + log(`getting ${target.module.name.full}.${prop}: (${target.module.identifiers[prop]}|${typeof target.context[prop]})`); + const DNEText = `${target.module.name.full}.${prop.toString()} either does not exist, or is not accessible`; + if(prop === 'restore') throw new Error(DNEText); + + if(prop in target.module.functions) { + return target.context[prop]; + } + throw new Error(DNEText); + } + }); + } + + restore() { + return this.context.restore?.(); + } + + get link () { + return this._link; + } +} \ No newline at end of file diff --git a/src/KV.ts b/src/KV.ts new file mode 100644 index 0000000..795fc4d --- /dev/null +++ b/src/KV.ts @@ -0,0 +1,3 @@ +export type KV = { + [key: string]: any +}; \ No newline at end of file diff --git a/src/Module.ts b/src/Module.ts new file mode 100644 index 0000000..5e9f3a7 --- /dev/null +++ b/src/Module.ts @@ -0,0 +1,135 @@ +import { + createAst, + DirectiveRule, + FunctionRule, + ImportRule, + LinkRule, + NamespaceRule, + Rule, + VariableRule +} from './createAst.js' +import path from 'path'; +import debug from 'debug'; +import { createRequire } from 'module'; +import { pathToFileURL } from 'url'; +const log = debug('vogue:module'); + +export type Link = { + name: string, + array: boolean, + required: boolean +}; + +export type Variable = { + name: string, + persist: boolean +} + +export default class Module { + links: Link[] = []; + globals = []; + functions: { + [name: string]: { + code: string, + async: boolean, + parameters: string[] + } + } = {}; + identifiers: { + [name: string]: Rule["type"] + } = {}; + name = { + space: '', + last: '', + full: '' + }; + imports: { + [key: string]: any + } = {}; + variables: Variable[] = []; + // directives + 'singleton': boolean = false; + 'keepalive': boolean = false; + 'static': string = ''; + // other stuff + rootDir: string = ''; + + async directive({ directive, value }: DirectiveRule): Promise { + if (typeof this[directive] === 'boolean') + (this[directive] as boolean) = value as boolean; + else if (typeof this[directive] === 'string') + (this[directive] as string) = value as string; + // = value as string; + } + + async link({ required, array, name }: LinkRule): Promise { + this.links.push({ + name, + required, + array + }); + } + + async namespace({ namespace }: NamespaceRule): Promise { + this.name.space = namespace; + this.name.full = this.name.space + '.' + this.name.last; + } + + async function({ name, block, parameters, async }: FunctionRule): Promise { + this.functions[name] = { + code: block, + parameters, + async + }; + } + + async import({ importName, name }: ImportRule): Promise { + const nodePath = path.resolve(this.rootDir, 'node_module'); + const __require__ = createRequire(nodePath); + const imported = __require__(importName); + if ('default' in imported) this.imports[name] = imported.default; + else this.imports[name] = imported; + } + + async variable({ persist, name }: VariableRule): Promise { + this.variables.push({ + name, + persist + }); + } + + static async create(location: string, rootDir: string) { + const module = new Module(); + const ast = createAst(location); + const name = path.parse(location).name; + + module.name.last = name; + module.name.full = name; + module.rootDir = rootDir; + + for (const item of ast) { + if ('name' in item) { + if (item.name in module.identifiers) + throw new Error('Identifier ' + item.name + ' already declared!'); + else { + module.identifiers[item.name] = item.type; + } + } + + log(`processing AST Rule (${'name' in item ? name + '|' : '' }${item.type})`); + // log(item); + + if (item.type in module) { + const func = module[item.type] as ((arg0: Rule) => Promise) + func.call(module, item); + } + } + + log('='.repeat(80)); + log(location); + log(module); + + return module; + } +} + diff --git a/Serializable.js b/src/Serializable.ts similarity index 70% rename from Serializable.js rename to src/Serializable.ts index f58882e..c410650 100644 --- a/Serializable.js +++ b/src/Serializable.ts @@ -1,7 +1,11 @@ // import { Ubjson } from '@shelacek/ubjson'; import { existsSync, readFileSync, writeFileSync } from 'fs'; +import { KV } from './KV'; export default class Serializable { + + constructor(...args: any[]) {} + // things that need to be stored only in cold // storage are keyed with a special prefix static CLASS_REFERENCE = '$$CLASS_NAME'; @@ -13,25 +17,29 @@ export default class Serializable { start() {} - toUbj() { - return Ubjson.encode(this.toSerializableObject()); - } + // toUbj() { + // return Ubjson.encode(this.toSerializableObject()); + // } - static fromUbj(buffer) { - return this.fromSerializableObject(Ubjson.decode(buffer)); - } + // static fromUbj(buffer) { + // return this.fromSerializableObject(Ubjson.decode(buffer)); + // } toJson() { return JSON.stringify(this.toSerializableObject(), null, 2); } - static fromJson(str) { + static serializationDependencies(): any[] { + return []; + } + + static fromJson(str: string) { return this.fromSerializableObject(JSON.parse(str)); } toSerializableObject() { - const transformValue = (val) => { + const transformValue = (val: any): any => { if(Array.isArray(val)) { return transformArray(val); } else if (val === null || val === undefined) { @@ -43,8 +51,8 @@ export default class Serializable { } } - const transformObject = (obj) => { - const clone = {}; + const transformObject = (obj: KV): KV => { + const clone: KV = {}; for(const prop of Object.keys(obj)) { if(prop.startsWith('_')) continue; @@ -56,7 +64,7 @@ export default class Serializable { return clone; } - const transformArray = (arr) => { + const transformArray = (arr: any[]): any[] => { const clone = []; for(const item of arr) { clone.push(transformValue(item)); @@ -67,10 +75,10 @@ export default class Serializable { return transformObject(this); } - static fromSerializableObject(obj) { + static fromSerializableObject(obj: KV) { if(obj[Serializable.CLASS_REFERENCE] !== this.name) return null; - const transformValue = (val) => { + const transformValue = (val: any): any => { if(Array.isArray(val)) { return transformArray(val); } else if(val === null || val === undefined) { @@ -78,7 +86,9 @@ export default class Serializable { } else if(typeof val === 'object') { if(Serializable.CLASS_REFERENCE in val) { const classes = this.serializationDependencies(); - const matchingClasses = classes.filter(classObject => classObject.name === val[Serializable.CLASS_REFERENCE]); + const matchingClasses = classes.filter((classObject) => { + classObject.name === val[Serializable.CLASS_REFERENCE] + }); if(matchingClasses.length === 1) { return matchingClasses[0].fromSerializableObject(val); } else { @@ -91,8 +101,8 @@ export default class Serializable { } } - const transformObject = (obj) => { - const clone = {}; + const transformObject = (obj: KV): KV => { + const clone: KV = {}; for(const prop of Object.keys(obj)) { if(prop.startsWith('_')) continue; @@ -101,7 +111,7 @@ export default class Serializable { return clone; } - const transformArray = (arr) => { + const transformArray = (arr: any[]): any[] => { const clone = []; for(const item of arr) { clone.push(transformValue(item)); @@ -125,7 +135,7 @@ export default class Serializable { switch(encoding) { case 'json': return this.toJson(); case 'ubjson': - case 'ubj': return this.toUbj(); + // case 'ubj': return this.toUbj(); default: { throw new TypeError('Unknown encoding: ' + encoding); } @@ -133,14 +143,14 @@ export default class Serializable { } - static deserialize(obj, { + static deserialize(obj: any, { encoding = 'json' } = {}) { switch(encoding) { case 'json': return this.fromJson(obj); case 'ubjson': - case 'ubj': return this.fromUbj(obj); + // case 'ubj': return this.fromUbj(obj); default: { throw new TypeError('Unknown encoding: ' + encoding); } @@ -149,32 +159,40 @@ export default class Serializable { async restore() {} - static createFromDisk(filename, ...args) { + static createFromDisk(filename: string, ...args: any[]) { if(existsSync(filename)) { const instance = this.deserialize(readFileSync(createFilepath(filename))); + // TS is plain and simply wrong... symbols can be used to index object... + // @ts-ignore instance[Serializable.PERSIST_LOCATION] = createFilepath(filename); - instance.restore(); + instance?.restore(); return instance; } else { const instance = new this(...args); + // again... TS is wrong... + // @ts-ignore instance[Serializable.PERSIST_LOCATION] = createFilepath(filename); - instance.updateDisk(); + instance?.updateDisk(); return instance; } } - updateDisk(filepath) { + updateDisk(filepath?: string) { // if it hasnt yet been written to disk... // this can happen if the contrustor // was called outside of createFromDisk if(filepath) { + // see above... TS7053 is just _wrong_. incorrect. thats not how JS works. + // @ts-ignore this[Serializable.PERSIST_LOCATION] = createFilepath(filepath); } const data = this.serialize(); + // this is getting annoying... + // @ts-ignore writeFileSync(this[Serializable.PERSIST_LOCATION], data); } } -function createFilepath(path) { +function createFilepath(path: string) { return `data/${path}`; } \ No newline at end of file diff --git a/System.js b/src/System.ts similarity index 70% rename from System.js rename to src/System.ts index 7ab0862..0d51240 100644 --- a/System.js +++ b/src/System.ts @@ -7,13 +7,22 @@ const log = debug('vogue:system') const {get, set} = _; -export default class System extends Serializable { - instances = []; - modules = null; - namespace = null; - staticInstances = {}; +type ModuleNamespaceMap = { + [key: string]: ModuleNamespaceMap | Module +}; - constructor(modules, rootDir) { +type ModuleName = string; + +class System extends Serializable { + instances: Instance[] = []; + modules: Module[]; + namespace: ModuleNamespaceMap = {}; + staticInstances: { + [key: string]: Instance + } = {}; + rootDir: string; + + constructor(modules: Module[], rootDir: string) { super(); this.modules = modules; this.createNamespace(); @@ -70,19 +79,22 @@ export default class System extends Serializable { }, {}); } - getModule(name) { - return get(this.namespace, name); + getModule(name: ModuleName): Module { + const module = get(this.namespace, name); + if(module instanceof Module) return module; + else throw Error(`${name} is not a module`); } - createInstance(name, args = {}) { - return new Instance(this.getModule(name), null, args, this); + createInstance(name: ModuleName, args = {}) { + return new Instance(this.getModule(name), '', args, this); } - newInstance(name, args = {}) { + newInstance(name: ModuleName, args = {}) { const instance = this.createInstance(name, args); const link = instance.link; - if(instance.hasPublicFunction('restore')) - instance.invokeInternal('restore'); + instance.restore(); return link; } -} \ No newline at end of file +} + +export default System; \ No newline at end of file diff --git a/createAst.js b/src/createAst.ts similarity index 68% rename from createAst.js rename to src/createAst.ts index 466508f..e527371 100644 --- a/createAst.js +++ b/src/createAst.ts @@ -1,8 +1,14 @@ import nearley from 'nearley'; +// TODO none of these shits have typings, but its OKAY +// @ts-ignore import compile from 'nearley/lib/compile.js'; +// @ts-ignore import generate from 'nearley/lib/generate.js'; +// @ts-ignore import nearleyGrammar from 'nearley/lib/nearley-language-bootstrapped.js'; +// @ts-ignore import moo from 'moo'; + import tokens from './tokens.js'; import { readFileSync } from 'fs'; import debug from 'debug'; @@ -11,7 +17,7 @@ import { fileURLToPath } from 'url'; import minify from './minify.js'; const log = debug('vogue:ast'); -const grammarFile = resolve(fileURLToPath(dirname(import.meta.url)), 'grammar.ne'); +const grammarFile = resolve(fileURLToPath(dirname(import.meta.url)), '..', 'lib', 'grammar.ne'); log('grammarFile:', grammarFile); function createParser() { @@ -53,10 +59,62 @@ function createParser() { eval(grammarJs); const grammar = module.exports; + // THESE IS COMPLICATED SHITS, IDK MAN WHAT ARE TYPINGS + // @ts-ignore return new nearley.Parser(nearley.Grammar.fromCompiled(grammar)) } -export default function createAst(location) { + +export type FunctionRule = { + type: 'function', + name: string + block: string, + parameters: string[], + async: boolean +}; + +export type VariableRule = { + type: 'variable', + persist: boolean, + name: string +}; + +export type NamespaceRule = { + type: 'namespace', + namespace: string +}; + +export type ImportRule = { + type: 'import', + name: string, + importName: string +}; + +export type LinkRule = { + type: 'link', + array: boolean, + required: boolean, + name: string +} + +export type DirectiveValue = string | boolean; + +export type DirectiveRule = { + type: 'directive', + directive: 'static' | 'singleton' | 'keepalive', + value: DirectiveValue +} + +export type Rule = FunctionRule + | VariableRule + | ImportRule + | DirectiveRule + | LinkRule + | NamespaceRule; + +export type AST = Rule[]; + +export function createAst(location: string): AST { const parser = createParser(); const contents = readFileSync(location).toString(); diff --git a/extensions.js b/src/extensions.ts similarity index 100% rename from extensions.js rename to src/extensions.ts diff --git a/minify.js b/src/minify.ts similarity index 81% rename from minify.js rename to src/minify.ts index e2ea8d8..20535d1 100644 --- a/minify.js +++ b/src/minify.ts @@ -1,7 +1,7 @@ import uglify from 'uglify-js'; -export default (code) => { +export default (code: string): string => { return uglify.minify(code, { compress: { dead_code: true, diff --git a/run.js b/src/run.ts old mode 100755 new mode 100644 similarity index 76% rename from run.js rename to src/run.ts index 8372f30..ed37cc7 --- a/run.js +++ b/src/run.ts @@ -12,14 +12,14 @@ import System from './System.js'; import './extensions.js'; import { fileURLToPath } from 'url'; // globals inside grammar context -import minify from './minify.js'; +import minify from './minify'; const { get, set } = _; -const standardLibrary = resolve(fileURLToPath(dirname(import.meta.url)), 'lib'); +const standardLibrary = resolve(fileURLToPath(dirname(import.meta.url)), '..', 'lib', 'vogue'); (async () => { // TODO simplify this line gaddam - const ignoreDeps = (path) => parse(path).name !== 'node_modules'; + const ignoreDeps = (path: string) => parse(path).name !== 'node_modules'; const files = [ ...walkdirSync(systemLocation, ignoreDeps), @@ -37,10 +37,10 @@ const standardLibrary = resolve(fileURLToPath(dirname(import.meta.url)), 'lib'); const sys = new System(modules, systemLocation); })() -function walkdirSync(root, filter = () => true) { +function walkdirSync(root: string, filter: ((path: string) => boolean) = () => true): string[] { log('reading', root, '...'); const paths = readdirSync(root).map(v => resolve(root, v)); - const [ files, dirs ] = sift(paths.filter(filter), (v) => lstatSync(v).isFile()); + const [ files, dirs ] = sift(paths.filter(filter), (v: string) => lstatSync(v).isFile()); log(`files: ${files.length} | dirs: ${dirs.length}`); const rfiles = dirs.map(v => walkdirSync(v, filter)).reduce((a, v) => [...a, ...v], []); @@ -50,15 +50,8 @@ function walkdirSync(root, filter = () => true) { ]; } -/** - * - * @param {T[]} a - * @param {(v: T, i: number, a: T[]) => string} fn - * - * @returns {Object} - */ -function sift(a, fn) { - let left = [], right = []; +function sift(a: T[], fn: (v: T, i: number, a: T[]) => boolean): [T[], T[]] { + let left: T[] = [], right: T[] = []; for(let i = 0; i < a.length; i ++) { const v = a[i] const lr = !!fn(v, i, a); diff --git a/tokens.js b/src/tokens.ts similarity index 100% rename from tokens.js rename to src/tokens.ts diff --git a/test/counter.v b/test/counter.v new file mode 100644 index 0000000..3e04bf3 --- /dev/null +++ b/test/counter.v @@ -0,0 +1,9 @@ +member count; + +increment() { + count ++; +} + +getCount() { + return count; +} \ No newline at end of file diff --git a/test/main.v b/test/main.v index 8db8958..a901312 100644 --- a/test/main.v +++ b/test/main.v @@ -1,12 +1,22 @@ singleton; -link currentSave; +link counter; +link window; async restore { + // process.stdout.write(typeof console._link + '\n'); console.log('~ Welcome to Vogue ~'); // process.stdout.write(JSON.stringify(console, null, 2)) - this.currentSave ??= create('world', {}); + counter ??= create('counter', {}); + for(let i = 0; i < 10; i ++) + counter.increment(); // const choice = await console.choice('select a thing', ['a', 'b', 'c', 'd']); - await this.currentSave.render(); + console.log(counter.getCount()); + + // window ??= create('SDL.window', {}); + + // window.setScene() + + // await counter.render(); } \ No newline at end of file diff --git a/test/pawn.v b/test/pawn.v new file mode 100644 index 0000000..72a7433 --- /dev/null +++ b/test/pawn.v @@ -0,0 +1,6 @@ + + + +restore { + +} \ No newline at end of file diff --git a/test/places/forest.v b/test/places/forest.v deleted file mode 100644 index ccfc12c..0000000 --- a/test/places/forest.v +++ /dev/null @@ -1,11 +0,0 @@ -namespace places; - -required link world; -link[] roads; - -member nitrogen; - -restore { - this.nitrogen ??= Math.floor(Math.random() * 50); -} - diff --git a/test/places/population.v b/test/places/population.v deleted file mode 100644 index 8aff8b4..0000000 --- a/test/places/population.v +++ /dev/null @@ -1 +0,0 @@ -namespace places \ No newline at end of file diff --git a/test/world.v b/test/world.v index c59b7b4..2625b35 100644 --- a/test/world.v +++ b/test/world.v @@ -1,28 +1,16 @@ -link[] places; -link place; -link character; +link[] pawns; -import random from 'random-world'; +member map; +member size; restore { - if(this.places.empty) - this.createPlaces(); + for(let i = 0; i < 3; i ++) { - this.character ??= create('') + } + + this.size ??= 64; } async render() { -} - -createPlaces() { - for(let i = 0; i < 10; i ++) { - const name = random.city(); - const valid = !!name.match(/^[A-Za-z ]*$/); - if(!valid) { - i --; - continue; - } - console.log(name); - } } \ No newline at end of file diff --git a/testinglib/window.v b/testinglib/window.v new file mode 100644 index 0000000..11cf894 --- /dev/null +++ b/testinglib/window.v @@ -0,0 +1,33 @@ +namespace SDL; + +keepalive; + +import sdl from '@kmamal/sdl'; +import util from 'util'; + +runtime member window; + +async restore { + // console.log('he...hello?') + window = sdl.video.createWindow({ + // borderless: true, + height: 200, + width: 300, + resizable: true + }); + + main_loop: + for (;;) { + let event + while ((event = sdl.events.poll())) { + console.log(event); + if (event.type === 'quit') { + window.destroy() + break main_loop + } + } + + + + } +} \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..8dd7b2a --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,15 @@ +{ + "compilerOptions": { + "module": "esnext", + "moduleResolution": "node", + "strict": true, + "allowSyntheticDefaultImports": true, + "target": "esnext", + "outDir": "out", + "sourceMap": true, + "declaration": true + }, + "include": [ + "src/**/*.ts" + ] +} \ No newline at end of file diff --git a/vogue-0.0.1.tgz b/vogue-0.0.1.tgz new file mode 100644 index 0000000..7b94f1e Binary files /dev/null and b/vogue-0.0.1.tgz differ diff --git a/yarn.lock b/yarn.lock index 9c2a0bd..3bfd784 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,6 +2,28 @@ # yarn lockfile v1 +"@types/debug@^4.1.5": + version "4.1.5" + resolved "https://registry.npmjs.org/@types/debug/-/debug-4.1.5.tgz" + +"@types/lodash@^4.14.169": + version "4.14.169" + resolved "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.169.tgz" + +"@types/nearley@^2.11.1": + version "2.11.1" + resolved "https://registry.npmjs.org/@types/nearley/-/nearley-2.11.1.tgz" + +"@types/node@^15.3.0": + version "15.3.0" + resolved "https://registry.npmjs.org/@types/node/-/node-15.3.0.tgz" + +"@types/uglify-js@^3.13.0": + version "3.13.0" + resolved "https://registry.npmjs.org/@types/uglify-js/-/uglify-js-3.13.0.tgz" + dependencies: + source-map "^0.6.1" + async@0.2.10: version "0.2.10" resolved "https://registry.npmjs.org/async/-/async-0.2.10.tgz" @@ -18,7 +40,7 @@ commander@^2.19.0: cross-env@^7.0.3: version "7.0.3" - resolved "https://registry.yarnpkg.com/cross-env/-/cross-env-7.0.3.tgz#865264b29677dc015ba8418918965dd232fc54cf" + resolved "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz" dependencies: cross-spawn "^7.0.1" @@ -32,7 +54,7 @@ cross-spawn@^7.0.1: debug@^4.3.1: version "4.3.1" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.1.tgz#f0d229c505e0c6d8c49ac553d1b13dc183f6b2ee" + resolved "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz" dependencies: ms "2.1.2" @@ -80,7 +102,7 @@ moo@^0.5.0, moo@^0.5.1: ms@2.1.2: version "2.1.2" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + resolved "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz" nearley@^2.20.1: version "2.20.1" @@ -130,6 +152,18 @@ shebang-regex@^3.0.0: version "3.0.0" resolved "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz" +source-map@^0.6.1: + version "0.6.1" + resolved "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz" + +supervisor@^0.12.0: + version "0.12.0" + resolved "https://registry.npmjs.org/supervisor/-/supervisor-0.12.0.tgz" + +typescript@^4.2.4: + version "4.2.4" + resolved "https://registry.npmjs.org/typescript/-/typescript-4.2.4.tgz" + uglify-js@^3.13.5: version "3.13.5" resolved "https://registry.npmjs.org/uglify-js/-/uglify-js-3.13.5.tgz" @@ -146,4 +180,4 @@ which@^2.0.1: yarn@^1.22.10: version "1.22.10" - resolved "https://registry.yarnpkg.com/yarn/-/yarn-1.22.10.tgz#c99daa06257c80f8fa2c3f1490724e394c26b18c" + resolved "https://registry.npmjs.org/yarn/-/yarn-1.22.10.tgz"