3 · Types
Every base type T has a partner T?. A T? is either known(v: T, grounds) or abstained(reason: Text). The two are disjoint from null, which does not exist.
This is a design draft written for review. Anything marked (proposal) is not settled. Section 12 lists what is not known yet.
let var fn if else for in match known abstain know grounded validate use return
program = { item } ;
item = fn_decl | let_stmt | stmt ;
fn_decl = "fn" IDENT "(" [ params ] ")" "->" type [ "validate" IDENT ] block ;
type = base [ "?" ] ; (* T? : known or abstained *)
base = IDENT [ "<" type { "," type } ">" ] ;
stmt = let_stmt | for_stmt | match_stmt | expr ;
know_expr = "know" expr [ "as" IDENT ] "=>" expr
"else" "=>" ( expr | abstain ) ;
abstain = "abstain" text ;
match_stmt= "match" expr "{" known_arm abstain_arm "}" ; (* both arms, either order *)
known_arm = "known" IDENT "=>" expr ;
abstain_arm = "abstain" IDENT "=>" expr ;
Every base type T has a partner T?. A T? is either known(v: T, grounds) or abstained(reason: Text). The two are disjoint from null, which does not exist.
match on a T? must contain a known arm and an abstain arm. A missing arm is error E013.
Passing a T? where T is expected is error E012. The two ways out are match, or the default form: x else value.
(proposal) Inside a function returning U?, the postfix x? unwraps a T? or returns its abstention upward, keeping the reason and adding the call site to its trail.
(proposal, v0.3) Every known value has a grounds set. Literals ground themselves. know … as r grounds the result on r. Operations union the grounds of their operands. grounds is read-only.
validate strict checks the returned value against the declared type, including allowed values and required fields. A failure becomes an abstention with reason “invalid result”, never a value that reaches the caller.
Errors (I/O failure, a bug) are separate from abstentions and stop the program unless caught with try. An abstention can never be turned into an error implicitly.
Polyglot values enter as T?: a JavaScript undefined or Java null becomes an abstention with reason “foreign null”.
(proposal, v1.0) tool and agent declare knows / unknown clauses. An agent's output is validated against its return type; free text cannot satisfy a structured type.
See the open questions page. They are part of the spec on purpose.