SkillAgentSearch skills...

Aa

Cliff Click Language Hacking

Install / Use

/learn @cliffclick/Aa
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

aa

Cliff Click Language Hacking

To-the-metal performance: every abstraction used can be peeled away, yielding code that you would expect from a tightly written low-level program. This is a primary driver for me, the guy who's been writing compilers for high performance computing (including Java) all my life. Ease-of-programming is a close second, but only after you've declared that performance is not your main goal. Hence I support syntactic sugar on expensive operations (e.g. accidental auto-boxing in a hot loop can cost you 10x in speed) but only if the type-system cannot remove it and you've not declared that you are programming for speed.

Modern: Statically typed. Functional programming with full-strength type inference - types are everywhere optional. Minimal syntax. REPL (i.e. incremental static typing) and separate compilation. Typed C-style macros: most syntax errors in dead code are typed.

My intent is a modern language that can be used where C or C++ is used: low-level high-performance work and a systems implementation language (e.g. OS's, device drivers, GC's), but bring in all the goodness of the last 20 years of language improvements.

The language is intended to "look like" C or Java, but with all types optional and all keywords removed. The whole no-keywords thing is an experiment I may back away from; a primary goal is to be readable - sometimes keywords feel like clutter and sometimes they are an code-anchor for your scanning eye.

I specifically intend to look at real-time constraints, and the notion of Time in a language.

Part of modern coding is the use of Garbage Collection, and the structured use of malloc/free - so I intend to add Rust-style memory management.

Part of modern coding is the use of multiple cores, so I intend to explore a couple of different concurrency models. A notion of a true 'final' field, made with a final-store (as opposed to declared as a final type) - you can make cyclic final structures, and once final all future reads will see the final value. No odd exceptions for "early publishing" a pointer.

And of course, this is a Work-In-Progress!!!!

GRAMMAR

BNF | Comment --- | ------- prog = stmts END | stmts= [tstmt or stmt][; stmts]*[;]? | multiple statments; final ';' is optional tstmt= tvar = :type | type variable assignment stmt = [id[:type] [:]=]* ifex | ids are (re-)assigned, and are available in later statements. stmt = ^ifex | Early function exit ifex = apply | ifex = apply ? stmt | trinary logic; the else-clause will default to 0 ifex = apply ? stmt : stmt | trinary logic apply = expr+ | Lisp-like application-as-adjacent, e.g. str 5 expr = term [binop term]* | gather all the binops and sort by prec term = uniop term | Any number of uniops term = id++ | post-inc/dec operators term = id-- | post-inc/dec operators term = tfact bop+ stmts bop- | Balanced/split operator arity-2, e.g. array lookup, ary [ idx ] term = tfact bop+ stmts bop- stmt | Balanced/split operator arity-3, e.g. array assign, ary [ idx ]:= val term = tfact post | A term is a tfact and some more stuff... post = empty | A term can be just a plain 'tfact' post = (tuple) post | Application argument list post = .field post | Field and tuple lookup post = .field [:]= stmt | Field (re)assignment. Plain '=' is a final assignment post = .field++ OR .field-- | Field reassignment. tfact= fact[:type] | Optionally typed fact fact = id | variable lookup fact = num | number fact = "string" | string fact = bop+ stmts bop- | Balanced/split operator, arity-1, e.g. array decl with size: [ 17 ] fact = bop+ [stmts,[stmts,]*] bop- | Balanced/split operator, arity-N, e.g. array decl with elements: [ "Cliff", "John", "Lisa" ] fact = (stmts) | General statements parsed recursively fact = tuple | Tuple builder fact = func | Anonymous function declaration fact = @{ stmts } | Anonymous struct declaration; assignments declare fields fact = {binop} | Special syntactic form of binop; no spaces allowed; returns function constant fact = {uniop} | Special syntactic form of uniop; no spaces allowed; returns function constant tuple= ( stmts,[stmts,] ) | Tuple; final comma is optional binop= +-*%&/<>!= [] ]= | etc; primitive lookup; can determine infix binop at parse-time, also pipe but GFM screws up uniop= -!~ [] | etc; primitive lookup; can determine infix uniop at parse-time bop+ = [ | Balanced/split operator open bop- = ] ]= ]:= | Balanced/split operator close func = { [id[:type]* ->]? stmts } | Anonymous function declaration, if no args then the -> is optional str = [.\%]* | String contents; \t\n\r% standard escapes str = %[num]?[.num]?fact | Percent escape embeds a 'fact' in a string; "name=%name\n" type = tcon OR tvar OR tfun[?] OR tstruct[?] OR ttuple[?] | // Types are a tcon or a tfun or a tstruct or a type variable. A trailing ? means 'nilable' tcon = int, int[1,8,16,32,64], flt, flt[32,64], real, str[?] | Primitive types tfun = { [[type]* ->]? type } | Function types mirror func decls ttuple = ( [[type],]* ) | Tuple types are just a list of optional types; the count of commas dictates the length, zero commas is zero length. Tuple fields are always final. tstruct = @{ [id [tfld];]* } | Struct types are field names with optional types or values. tfld = ! : type ! = ifex | Fields are untyped or typed or final-assigned (with computed expression type) tvar = id | Type variable lookup

SIMPLE EXAMPLES

Code | Comment ---- | ------- 1 | 1:int Prefix unary operator | --- -1 | -1:int application of unary minus to a positive 1 !1 | 0:int convert 'truthy' to false Infix binary operator | --- 1+2 | 3:int 1-2 | -1:int 1<=2 | 1:int Truth === 1 1>=2 | 0:int False === 0 Binary operators have precedence | --- 1+2*3 | 7:int standard precedence 1+2 * 3+4 *5 | 27:int (1+2)*(3+4)*5 | 105:int parens overrides precedence 1// some comment<br>+2 | 3:int with bad comment 1 < 2 | 1:int true is 1, 1 is true 1 > 2 | 0:int false is 0, 0 is false Float | --- 1.2+3.4 | 4.6:flt 1+2.3 | 3.3:flt standard auto-widening of int to flt 1.0==1 | 1:int True; int widened to float Simple strings | --- "Hello, world"| "Hello, world":str str(3.14) | "3.14":str Overloaded str(:flt) str(3) | "3":str Overloaded str(:int) str("abc") | "abc":str Overloaded str(:str) Variable lookup | --- math_pi | 3.141592653589793:flt Should be math.pi but name spaces not implemented primitive function lookup | --- + | "Syntax error; trailing junk" unadorned primitive not allowed _+_ | {{+:{int int -> int}, +:{flt flt -> flt}} returns a union of '+' functions. The underscores indicate a binary op {_+_} | Same as above {!_} | !:{int -> int1} function taking an int and returning a bool. The under indicates a prefix unary op Function application, traditional paren/comma args | --- _+_(1,2) | 3:int _-_(1,2) | -1:int binary version -_(1) | -1:int unary version Errors; mismatch arg count | --- !() | Call to unary function '!', but missing the one required argument math_pi(1) | A function is being called, but 3.141592653589793 is not a function type _+_(1,2,3) | Passing 3 arguments to +{flt64 flt64 -> flt64} which takes 2 arguments Arguments separated by commas and are full statements | --- _+_(1, 2 * 3) | 7:int _+_(1 + 2 * 3, 4 * 5 + 6) | 33:int (1;2 ) | 2:int just parens around two statements (1;2;) | 2:int final semicolon is optional _+_(1;2 ,3) | 5:int full statements in arguments Syntax for variable assignment | --- x=1 | 1:int assignments have values x:=1 | 1:int Same thing, not final x=y=1 | 1:int stacked assignments ok x=y= | Missing ifex after assignment of 'y' x=1+y | Unknown ref 'y' x=2; y=x+1; x*y | 6:int 1+(x=2*3)+x*x | 43:int Re-use ref immediately after def; parses as: x=(2*3); 1+x+x*x x=(1+(x=2)+x) | Cannot re-assign ref 'x' x=(1+(x:=2)+x) | 5:int RHS executes first, so parses as: x:=2; x=1+x+x x++ | 0:int Define new variable as 0, and return it before the addition x:=0; x++; x | 1:int Define new variable as 0, then add 1 to it, then return it x++ + x-- | 1:int Can be used in expressions Conditionals | --- 0 ? 2 : 3 | 3:int Zero is false 2 ? 2 : 3 | 2:int Any non-zero is true; "truthy" math_rand(1)?(x=4):(x=3);x | :int8 x defined on both arms, so available after but range bound math_rand(1)?(x=2): 3 ;4 | 4:int x-defined on 1 side only, but not used thereafter math_rand(1)?(y=2;x=y*y):(x=3);x | :int8 x defined on both arms, so available after, while y is not math_rand(1)?(x=2): 3 ;x | 'x' not defined on false arm of trinary No partial-defs math_rand(1)?(x=2): 3 ;y=x+2;y | 'x' not defined on false arm of trinary More complicated partial-def math_rand(1)?1 | :int1 Can skip last arm, will default to 0 x:=0; math_rand(1) ? x++; x | :int1 Side effects in the one arm 0 ? (x=2) : 3;x | `'x' not defined on false arm

Related Skills

View on GitHub
GitHub Stars291
CategoryDevelopment
Updated10d ago
Forks24

Languages

Java

Security Score

95/100

Audited on Mar 23, 2026

No findings