You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Since the code and its execution can be entirely understood, we can draft the type based on known information:
/*** * A person interface * @Person Struct * @name String * @age Number? * @ssn UNKNOWN // WARN: incomplete use / conflict * @friend String|Person * * $version draft ef2b31 // drafted, non-authoritative * // can be updated by tooling */
Note: draft means that we should not use the type comment to enforce what the code should be, but rather we re-gen on code update. Anytime the code is correct and the type definition is out-of-date we can change the $version to draft to allow it to be regenerated.
varPerson={}/*** * @Create // the constructor type * @opts Person{ // sub-interface definition * name, * age?, * ssn, * friend?, * } * // (properties have the same type as Person) * returns @Person */Person.create=function(opts){varp={};p.name=opts.name// requiredp.age=opts.age||0// optionalp.ssn=opts.ssn// WARN: ambiguousp.friend=opts.friend||p// enumreturnp;}Person.create({name: "Jack",age: 42,friend: "Jeff"});
We can tell by the usage what a Person object can and can't be.
Concrete types
/*** * A person (or person-esque) interface * @Person Struct // Object, sans prototype stuff * @name String // common String * @age NaturalNumber|null // 1 to MAX_SAFE_INTEGER, or null * @bankBalance BigInt // can be pos, neg, or 0! (probably in pennies) * @friends []Person // friend list or null * @favoritePet Pet|null? // pet or null or not defined * * $version v1.0.1 // whether the type has been locked *//*** @Person */varPerson={};Person.name="AJ";Person.age=0;
To create an ad-hoc new type:
functiongetInterestingType(){/*** @KnownType */varknownType={foo: "bar"}varnewProperties={bar: "baz"};varnewType=Object.assign(knownType,newProperties)}// this is now known to be KnowType-ish + `bar` and can be checked as such.varinterestingType=getInterestingType();
If a function can throw, that's part of its type information.
// not possible to throwfunctionadd(){varsum=2+5;returnsum;}
// can throwfunctiondivide(a,b){varquotient=a/b;returnquotient;}
note: this is an argument against allowing += in sub-index:
we can create template strings we can interpolate withouteval
functionexecTemplate(tmpl,{ friend, me }){varaccessors=tmpl.match(/magic/g);// ... magic{varval=getByMagic(accessorPath,friend);replaceByMagic(tmpl,accessorPath,val);}}
or we could have another type of expression just for
template strings that allows the simplest accessors,
but not invocations (potentially unsafe) or indexes + logic
Numbers
Some rough, not-well-thought-out ideas (Re: can division throw):
// 😉varSelfLoathing={};SelfLoathing.create=function(){vars={};s.name="evil";s.greet=function(other){return`Hello ${other}, I'm ${s.name}`;};returns;};// TODO how do we chose the name of `this` => `s`?// note: either `var s = { foo: bar, baz: quux }`// or `var s = {}; s.foo = bar; s.baz = quux;`// but not `var s = { foo: bar }; s.baz = quux;`
Syntax
Keywords
These words cannot be used for standalone variable or function names, but may be used as property names.
(30) arguments, async, await, break, case, catch, const, continue, debugger, default, delete, else, export, exports, false, for, function, if, import, in, let, null, return, require , switch, throw, true, try, typeof, undefined, var, void
Idea: can we remove more without increasing pain?
(24) arguments, async, await, break, catch, continue, delete, else, export, exports, false, for, function, if, import, in, null, return, require, throw, true, try, typeof, undefined, var, void
(unused: case, debugger, default, switch, import, export, var, const)
Table of Contents
Questions
(probably not since you can't unwind an async stack)
Guiding Principles
Language Principles
Syntax Principles
(no prototypes, no inheritance, no chaining, no reduce)
(at the expense of expressiveness and the tax of verbosity)
Ai JitScript by Example
Type System
Duck-Typing is King! (everything is an interface)
TitleCase
(because we can tell if a property exists?)
Type Drafting
Types can be inferred from correct code, and drafted automatically.
Consider this code:
Since the code and its execution can be entirely understood, we can draft the type based on known information:
Note:
draft
means that we should not use the type comment to enforce what the code should be, but rather we re-gen on code update. Anytime the code is correct and the type definition is out-of-date we can change the$version
todraft
to allow it to be regenerated.We can tell by the usage what a Person object can and can't be.
Concrete types
To create an ad-hoc new type:
If a function can throw, that's part of its type information.
Functions
camelCase
return
async
(but cannot be generators)void
ed (for side effects)async
statements MUST be called withawait
async
expressions are valid if Promise is a valid typemain()
must be statically inspectablefn
) and the invocation ((
)Special Functions
async function main()
must exist for "bins"function create()
must NOT be asyncasync function init()
MUST be asyncVariables
var
only because...ALL_CAPS
Expressions
(the same as accessor expressions for now)
(access variables and properties)
(accessor expression ending with a function invocation)
(EXCEPTION: functions can be
void
ed, see Functions)(but not functions, see Functions)
arr
orobj
and[
Strings
+=
in sub-index:we can create template strings we can interpolate without
eval
template strings that allows the simplest accessors,
but not invocations (potentially unsafe) or indexes + logic
Numbers
Some rough, not-well-thought-out ideas (Re: can division throw):
Macro System
Think of
prettier
- the macro parser and expander executes on save.Syntax
Keywords
These words cannot be used for standalone variable or function names, but may be used as property names.
(30)
arguments
,async
,await
,break
,case
,catch
,const
,continue
,debugger
,default
,delete
,else
,export
,exports
,false
,for
,function
,if
,import
,in
,let
,null
,return
,require
,switch
,throw
,true
,try
,typeof
,undefined
,var
,void
Idea: can we remove more without increasing pain?
(24)
arguments
,async
,await
,break
,catch
,continue
,delete
,else
,export
,exports
,false
,for
,function
,if
,import
,in
,null
,return
,require
,throw
,true
,try
,typeof
,undefined
,var
,void
(unused:
case
,debugger
,default
,switch
,import
,export
,var
,const
)Special Words
of
new
(Unused) Reserved Words
These words are reserved for historical reasons.
do
,class
,enum
,eval
,extends
,finally
,function*
,implements
,instanceof
,interface
,let
,new
,package
,private
,protected
,public
,static
,super
,this
,while
,with
,yield
,yield*
Non-Reserved Words
These words might appear to be reserved, but they aren't.
abstract
,boolean
,byte
,char
,double
,final
,float
,goto
,int
,long
,native
,short
,synchronized
,throws
,transient
,volatile
Syntax Characters
Alphanumeric and Word Characters:
a-z
A-Z
0-9
_
,Identifiers can also contain:
$
Accessors may also use:
.
[
]
?.
(which is a pair, not?
and.
)Functions use:
(
,)
,
{
,}
Math Operations:
+
(but not++
or+=
or--
)*
,/
(but not*=
,\=
, or**=
)**
(likeMath.pow()
, but forBigInt
s)%
>
,<
,<=
,>=
===
(but not==
)Strings:
`
"
'
)Logical Operators:
!
!==
(but not!=
)&&
||
(and maaaaaybe||=
)??
((ex:
function ({ x = null }) { x = x ?? true }
)Bitwise Operators
~
^
, but not^=
&
, but not&=
|
, but not|=
<<
,>>>
(I'm not sure about>>
, no<<=
or>>=
)Other
for await
for ... in
(unexpected string keys)Special syntax
#!/usr/bin/env bun
#!/usr/bin/env node
#!/usr/bin/env deno
No-Conflict
Cannot be in conflict with https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Grammar_and_types or https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators
Nutty Things
void
is among the Browser's best-kept secrets:The text was updated successfully, but these errors were encountered: