// Declaration restriction tests // Run: ./cell tests/decl_restrictions.ce var tokenize = use("tokenize") var parse = use("parse") var passed = 0 var failed = 0 var error_names = [] var error_reasons = [] var fail_msg = "" var _i = 0 for (_i = 0; _i < 20; _i++) { error_names[] = null error_reasons[] = null } var fail = function(msg) { fail_msg = msg disrupt } var run = function(name, fn) { fail_msg = "" fn() passed = passed + 1 } disruption { error_names[failed] = name error_reasons[failed] = fail_msg == "" ? "disruption" : fail_msg failed = failed + 1 } var parse_snippet = function(src) { var result = tokenize(src, "") var ast = parse(result.tokens, src, "", tokenize) return ast } var has_error = function(ast, substring) { if (ast.errors == null) return false var i = 0 while (i < length(ast.errors)) { if (search(ast.errors[i].message, substring) != null) return true i = i + 1 } return false } var has_no_errors = function(ast) { return ast.errors == null || length(ast.errors) == 0 } // === BARE BLOCK === run("bare block rejected", function() { var ast = parse_snippet("{ var x = 1 }") if (!has_error(ast, "bare block")) fail("expected 'bare block' error, got: " + text(ast.errors)) }) // === VAR IN IF (braces) === run("var in if braces", function() { var ast = parse_snippet("if (true) { var x = 1 }") if (!has_error(ast, "not inside 'if'")) fail("expected 'not inside if' error, got: " + text(ast.errors)) }) // === VAR IN IF (no braces) === run("var in if no braces", function() { var ast = parse_snippet("if (true) var x = 1") if (!has_error(ast, "not inside 'if'")) fail("expected 'not inside if' error, got: " + text(ast.errors)) }) // === VAR IN WHILE === run("var in while", function() { var ast = parse_snippet("while (true) { var x = 1; break }") if (!has_error(ast, "not inside 'while'")) fail("expected 'not inside while' error, got: " + text(ast.errors)) }) // === VAR IN FOR INIT === run("var in for init", function() { var ast = parse_snippet("for (var i = 0; i < 1; i++) {}") if (!has_error(ast, "for initializer")) fail("expected 'for initializer' error, got: " + text(ast.errors)) }) // === VAR IN FOR BODY === run("var in for body", function() { var ast = parse_snippet("var i = 0; for (i = 0; i < 1; i++) { var x = 1 }") if (!has_error(ast, "not inside 'for'")) fail("expected 'not inside for' error, got: " + text(ast.errors)) }) // === VAR IN DO === run("var in do", function() { var ast = parse_snippet("do { var x = 1; break } while (true)") if (!has_error(ast, "not inside 'do'")) fail("expected 'not inside do' error, got: " + text(ast.errors)) }) // === DEF IN IF === run("def in if", function() { var ast = parse_snippet("if (true) { def x = 1 }") if (!has_error(ast, "not inside 'if'")) fail("expected 'not inside if' error, got: " + text(ast.errors)) }) // === UNINITIALIZED VAR === run("uninitialized var", function() { var ast = parse_snippet("var x") if (!has_error(ast, "must be initialized")) fail("expected 'must be initialized' error, got: " + text(ast.errors)) }) // === NESTED: VAR IN IF INSIDE WHILE === run("nested var in if inside while", function() { var ast = parse_snippet("while (true) { if (true) { var x = 1 }; break }") if (!has_error(ast, "not inside 'if'")) fail("expected 'not inside if' error, got: " + text(ast.errors)) }) // === VALID: NESTED FUNCTION === run("valid nested fn in control flow", function() { var ast = parse_snippet("if (true) { var fn = function() { var x = 1; return x } }") // The var inside the function is fine; only the var fn = ... inside if should error if (!has_error(ast, "not inside 'if'")) fail("expected error for var fn inside if") // But there should NOT be an error about var x inside the function body var i = 0 var bad = false if (ast.errors != null) { while (i < length(ast.errors)) { if (search(ast.errors[i].message, "var x") != null) bad = true i = i + 1 } } if (bad) fail("should not error on var inside nested function") }) // === VALID: NORMAL VAR === run("valid normal var", function() { var ast = parse_snippet("var x = 1") if (!has_no_errors(ast)) fail("expected no errors, got: " + text(ast.errors)) }) // === VALID: VAR IN FUNCTION BODY === run("valid var in function body", function() { var ast = parse_snippet("var fn = function() { var x = 1; return x }") if (!has_no_errors(ast)) fail("expected no errors, got: " + text(ast.errors)) }) // === SUMMARY === print(text(passed) + " passed, " + text(failed) + " failed out of " + text(passed + failed)) var _j = 0 if (failed > 0) { print("") for (_j = 0; _j < failed; _j++) { print(" FAIL " + error_names[_j] + ": " + error_reasons[_j]) } } $stop()