diff --git a/bin/install b/bin/install index a2f18389..ca8450da 100755 --- a/bin/install +++ b/bin/install @@ -1,6 +1,6 @@ #!/usr/bin/env bash echo "Downloading..." -sudo npm install +npm install echo "Installing..." cpath="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" diff --git a/bin/path b/bin/path index 436d99d9..9caa30a0 100755 --- a/bin/path +++ b/bin/path @@ -16,10 +16,10 @@ if [ ! -d "$($rp "$cpath/../dist")" ]; then fi echo "Installing executable..." -sudo cp "$($rp "$cpath/../dist/cli/cheddar")" "$1/bin/" +cp "$($rp "$cpath/../dist/cli/cheddar")" "$1/bin/" echo "Installing cheddar..." sudo rm -rf "$1/share/cheddar" -sudo cp -r "$($rp "$cpath/../")" "$1/share/cheddar/" +cp -r "$($rp "$cpath/../")" "$1/share/cheddar/" echo echo "Cleaning up..." bash "$($rp "$cpath/cleanup")" "$1/share/cheddar" diff --git a/src/cli/repl.es6 b/src/cli/repl.es6 index 9f8d181e..d441dae1 100644 --- a/src/cli/repl.es6 +++ b/src/cli/repl.es6 @@ -8,6 +8,15 @@ import NIL from '../interpreter/core/consts/nil'; import cheddar from '../interpreter/exec'; import tokenizer from '../tokenizer/tok'; +/*== ENVIORNMENT GENERATION DEPENDENCIES ==*/ +// TODO Externalize this +import dep_String from '../interpreter/core/primitives/String'; +import dep_Bool from '../interpreter/core/primitives/Bool'; +import dep_Number from '../interpreter/core/primitives/Number'; +import dep_Array from '../interpreter/core/primitives/Array'; + +import CheddarVariable from '../interpreter/core/env/var'; + let REPL = readline.createInterface(process.stdin, process.stdout); REPL.setPrompt('cheddar> '.yellow.bold); REPL.prompt(); @@ -22,8 +31,13 @@ REPL.setPrompt = (prompt, length) => const REPL_ERROR = text => console.log("T_REPL:ERROR".red.underline.bold + " - ".dim + text); const REPL_HEAD = text => console.log(`━━ ${text} ━━`.bold.magenta); - -let GLOBAL_SCOPE = new CheddarScope(); +const CONSTANT = { Writeable: false }; +let GLOBAL_SCOPE = new CheddarScope(null, new Map([ + ["String" , new CheddarVariable(dep_String, CONSTANT)], + ["Number" , new CheddarVariable(dep_Number, CONSTANT)], + ["Array" , new CheddarVariable(dep_Array , CONSTANT)], + ["Boolean", new CheddarVariable(dep_Bool , CONSTANT)] +])); REPL.on('line', function(STDIN) { @@ -49,6 +63,10 @@ REPL.on('line', function(STDIN) { console.log( `${Output.constructor.Cast.get('String')(Output).value}`.magenta ); + } else if (Output instanceof CheddarScope) { + console.log(`< Instance of "${Output.constructor.Name}" >`); + } else if (Output.prototype instanceof CheddarScope) { + console.log(`< Class "${Output.Name}" >`); } else if (typeof Output === "symbol") { console.log(Output.toString().magenta); } else { diff --git a/src/interpreter/core/consts/err.es6 b/src/interpreter/core/consts/err.es6 index 8ffaac5b..2647dbce 100644 --- a/src/interpreter/core/consts/err.es6 +++ b/src/interpreter/core/consts/err.es6 @@ -8,6 +8,7 @@ export default { CANNOT_READ_PROP : Symbol('CANNOT_READ_PROP'), CAST_FAILED : Symbol('CAST_FAILED'), + NOT_A_CLASS : Symbol('NOT_A_CLASS'), UNLINKED_CLASS : Symbol('UNLINKED_CLASS'), MALFORMED_TOKEN : Symbol('MALFORMED_TOKEN'), diff --git a/src/interpreter/core/consts/err_msg.es6 b/src/interpreter/core/consts/err_msg.es6 index bb0e49c3..c130f687 100644 --- a/src/interpreter/core/consts/err_msg.es6 +++ b/src/interpreter/core/consts/err_msg.es6 @@ -1,7 +1,7 @@ import RuntimeError from './err'; export default new Map([ - [RuntimeError.KEY_NOT_FOUND, "Attempted to access undefined key $0"], + [RuntimeError.KEY_NOT_FOUND, "Attempted to access undefined variable ($0)"], [RuntimeError.KEY_IS_RESERVED, "Attempted to access reserved keyword $0"], [RuntimeError.NO_OP_BEHAVIOR, "`$0` has no behavior for types `$2` and `$1`"], diff --git a/src/interpreter/core/env/class.es6 b/src/interpreter/core/env/class.es6 index e089ebe4..5ca5d734 100644 --- a/src/interpreter/core/env/class.es6 +++ b/src/interpreter/core/env/class.es6 @@ -35,10 +35,11 @@ import CheddarScope from './scope'; import * as CheddarError from '../consts/err'; -import { DEFAULT_OP, DEFAULT_CAST } from './defaults'; +import { DEFAULT_OP, DEFAULT_CAST, IS_CLASS } from './defaults'; export default class CheddarClass extends CheddarScope { static Name = "UNDEFINED"; + // Define operators. Each item in the // hash-map, defines behavior for the // specific token in an OperatorToken diff --git a/src/interpreter/core/env/defaults.es6 b/src/interpreter/core/env/defaults.es6 index aa743b61..80a34f62 100644 --- a/src/interpreter/core/env/defaults.es6 +++ b/src/interpreter/core/env/defaults.es6 @@ -5,6 +5,9 @@ import CheddarError from '../consts/err'; import HelperInit from '../../../helpers/init'; +import CheddarClass from './class'; // I really hope this works >_> + +export const IS_CLASS = Symbol("IS_CLASS"); export const DEFAULT_OP = new Map([ // print: Definition @@ -24,11 +27,22 @@ export const DEFAULT_OP = new Map([ return LHS; }], + ['::', (LHS, RHS) => { + if (!LHS.prototype instanceof CheddarClass) + return CheddarError.CAST_FAILED; + + let res; + if ((res = RHS.constructor.Cast.get(LHS.Name))) { + return res(RHS); + } else { + return CheddarError.NO_OP_BEHAVIOR; + } + }], + ['==', (LHS, RHS) => { return HelperInit(require("../primitives/Bool"), RHS && LHS instanceof RHS.constructor && LHS.value === RHS.value); }] ]); - export const DEFAULT_CAST = new Map(); \ No newline at end of file diff --git a/src/interpreter/core/eval/eval.es6 b/src/interpreter/core/eval/eval.es6 index 079e87bf..666c866a 100644 --- a/src/interpreter/core/eval/eval.es6 +++ b/src/interpreter/core/eval/eval.es6 @@ -24,7 +24,7 @@ import {TYPE as OP_TYPE} from '../../../tokenizer/consts/ops'; // Reference tokens import CheddarPropertyToken from '../../../tokenizer/parsers/property'; import CheddarPrimitive from '../../../tokenizer/literals/primitive'; -import CheddarTypedLiteral from '../../../tokenizer/parsers/typed'; +import CheddarLiteral from '../../../tokenizer/parsers/any'; import CheddarOperatorToken from '../../../tokenizer/literals/op'; import CheddarArrayToken from '../../../tokenizer/parsers/array'; import CheddarVariableToken from '../../../tokenizer/literals/var'; @@ -108,38 +108,29 @@ export default class CheddarEval extends CheddarCallStack { this.put(OPERATOR); } - } else if (Operation instanceof CheddarTypedLiteral) { + } else if (Operation instanceof CheddarLiteral) { // If it is a token, pass tokens to the associated class constructor + TOKEN = Operation._Tokens[0]; // Get token - TOKEN = Operation.Tokens.pop(); // Get the top token (e.g. CheddarNumber) - Operation.Tokens.push(TOKEN); + // Do a lookup in the PRIMITIVE_LINKS class and get the link class + if ((OPERATOR = PRIMITIVE_LINKS.get(TOKEN.constructor.name))) { + // OPERATOR has the class to construct upon - // This means it is a cast/constructor because it has an additional arg - if (Operation.Tokens.length > 1) { - /* TODO: Implement */; - } else { - // Otherwise locate the class to link - // and the construct it - // Do a lookup in the PRIMITIVE_LINKS class and get the link class - if ((OPERATOR = PRIMITIVE_LINKS.get(TOKEN.constructor.name))) { - // OPERATOR has the class to construct upon - - // Operator Construction - OPERATOR = new OPERATOR(this.Scope); - - // Initialize operator class - // check if successful (true) - if ((TOKEN = OPERATOR.init(...TOKEN.Tokens)) === true) { - // place on stack - this.put( OPERATOR ); - } else { - // return error - return TOKEN; - } + // Operator Construction + OPERATOR = new OPERATOR(this.Scope); + // Initialize operator class + // check if successful (true) + if ((TOKEN = OPERATOR.init(...TOKEN.Tokens)) === true) { + // place on stack + this.put( OPERATOR ); } else { - return CheddarError.UNLINKED_CLASS; + // return error + return TOKEN; } + + } else { + return CheddarError.UNLINKED_CLASS; } } else if (Operation instanceof CheddarPropertyToken) { // If it's a property @@ -162,7 +153,8 @@ export default class CheddarEval extends CheddarCallStack { OPERATOR = this.Scope.accessor(Operation._Tokens[0]._Tokens[0]).Value; if (OPERATOR === CheddarError.KEY_NOT_FOUND || !OPERATOR) { - return CheddarError.KEY_NOT_FOUND; + return CheddarErrorDesc.get(CheddarError.KEY_NOT_FOUND) + .replace('$0', Operation._Tokens[0]._Tokens[0]); } } else { return CheddarError.MALFORMED_TOKEN; diff --git a/src/tokenizer/consts/ops.es6 b/src/tokenizer/consts/ops.es6 index 700ce191..9eeaff4b 100644 --- a/src/tokenizer/consts/ops.es6 +++ b/src/tokenizer/consts/ops.es6 @@ -20,7 +20,7 @@ export const RESERVED_KEYWORDS = new Set( export const OP = [ '!', '^', '*', '/', '%', '+', '-', '<=', '>=', '<', '>', '==', '&', '|', '!=', '=', '+=', '-=', '*=', '/=', '^=', '%=', '&=', '|=', '<<', '>>', '<<=', '>>=', -':', +':', '::', '@"', 'and', 'or', 'xor', // Unary operators @@ -32,11 +32,13 @@ export const OP = [ 'floor', 'ceil', 'round', 'len', 'reverse', 'abs', 'repr', 'sign', -'print']; +'print', +'new']; // TODO: how will the user modify this? no idea //TODO: fix precedence export const UNARY_PRECEDENCE = new Map([ + ['new', 21000], ['!', 20000], ['-', 20000], ['+', 20000], diff --git a/src/tokenizer/parsers/any.es6 b/src/tokenizer/parsers/any.es6 index 5a950461..b9ce997e 100644 --- a/src/tokenizer/parsers/any.es6 +++ b/src/tokenizer/parsers/any.es6 @@ -15,7 +15,8 @@ export default class CheddarAnyLiteral extends CheddarLexer { if (attempt instanceof CheddarLexer) { this.Index = attempt.Index; - return this.close(attempt); + this.Tokens = attempt; + return this.close(); } else { return this.error(attempt); } diff --git a/src/tokenizer/parsers/expr.es6 b/src/tokenizer/parsers/expr.es6 index 789bfa0d..828aa61d 100644 --- a/src/tokenizer/parsers/expr.es6 +++ b/src/tokenizer/parsers/expr.es6 @@ -1,7 +1,7 @@ // Cheddar Expression Parser import O from '../literals/op'; import P from './property'; -import L from './typed'; +import L from './any'; import F from './function'; import CheddarLexer from '../tok/lex'; import {OP, UOP, EXPR_OPEN, EXPR_CLOSE} from '../consts/ops'; diff --git a/src/tokenizer/parsers/typed.es6 b/src/tokenizer/parsers/typed.es6 index 7ba62fb3..5b4691f7 100644 --- a/src/tokenizer/parsers/typed.es6 +++ b/src/tokenizer/parsers/typed.es6 @@ -16,11 +16,4 @@ export default class CheddarTypedLiteral extends CheddarLexer { [CheddarAnyLiteral] ); } - static makeparser(arg) { - let passed = new CheddarLexer(); - passed.exec = function() { - return new CheddarTypedLiteral(this.Code, this.Index).exec(arg); - }; - return passed; - } } \ No newline at end of file diff --git a/test/vars.cdr b/test/vars.cdr index 003d0fd5..2fb48fad 100644 --- a/test/vars.cdr +++ b/test/vars.cdr @@ -1,3 +1,26 @@ -var a := "b" -var b := "c"; -const d := "e"; +var a := 1; +var _ := 2; +var $ := 3; +var _$:= 4; +var $_:= 5; +var a_:= 6; +var $a:= 7; +var a1:= 8; + +const a := 1; +const a := [1, 2, 3]; + +print a; +print _; +print $; +print _$; +print $_; +print a_; +print $a; +print a1; +print _+$+_$; +print [a,_,$,_$]; + +//@EACH +var 1a := 1; +var a = 1; \ No newline at end of file