Skip to content

Instantly share code, notes, and snippets.

@kl0tl
Last active August 29, 2015 14:02
Show Gist options
  • Select an option

  • Save kl0tl/3b9a283a4d18753604d3 to your computer and use it in GitHub Desktop.

Select an option

Save kl0tl/3b9a283a4d18753604d3 to your computer and use it in GitHub Desktop.
Existential operator `?`
/*
`a?()`
Call its operand only if it is defined and a `function`, returns `undefined` otherwise
`a?.b` or `a?['b']`
Access a property on its operand only if it is defined and not `null` nor `undefined`, returns `undefined` otherwise
`a ?= b`
Assign its right operand to its left operand only if the later is defined, not `null` nor `undefined` and returns the value, or `undefined` otherwise
`a ?? b`
Returns its left operand only if it is defined and not `null` nor `undefined`, or its right operand otherwise
`a?`
Returns `true` only if its operand is defined and not `null` nor `undefined`
Besides `?=` all existential operators can safely be used with undeclared variables
*/
macro function_arguments {
rule { ($argument:expr (,) ...) }
}
macro property_accessor {
rule { . $property:ident }
rule { [ $property:expr ] }
}
macro guard {
rule { $symbol:ident } => {
typeof $symbol === 'undefined' ? null : $symbol
}
}
let ? = macro {
/* TODO
rule infix { $symbol | $arguments:function_arguments $(? $next_arguments:function_arguments) ... } => {
(typeof $symbol === 'function' ? function (ref) {
return $((typeof ref) !== 'function' ? undefined :
ref = ref $next_arguments) (,) ...
}($symbol $arguments) : undefined)
}//*/
rule infix { $symbol:ident | $arguments:function_arguments } => {
(typeof $symbol === 'function' ? $symbol $arguments : undefined)
}
rule infix { $expression:expr | $arguments:function_arguments } => {
(function (ref) {
if (typeof ref === 'function') {
return ref $arguments
}
}($expression))
}
rule infix { $symbol:ident | . $head:ident ?. $($($next:ident ?) (.) ...) $tail:ident } => {
(function (ref) {
return (ref === null ? undefined :
(ref = ref.$head) == null ? undefined :
$((ref = ref.$next) == null ? undefined :) ...
ref) === undefined ? undefined : ref.$tail
}(guard $symbol))
}
rule infix { $expression:expr | . $head:ident ?. $($($next:ident ?) (.) ...) $tail:ident } => {
(function (ref) {
return (ref == null ? undefined :
(ref = ref.$head) == null ? undefined :
$((ref = ref.$next) == null ? undefined :) ...
ref) === undefined ? undefined : ref.$tail
}($expression))
}
rule infix { $symbol:ident | $property:property_accessor } => {
(function (ref) {
return ref == null ? undefined : ref $property
}(guard $symbol))
}
rule infix { $expression:expr | $property:property_accessor } => {
(function (ref) {
return ref == null ? undefined : ref $property
}($expression))
}
rule infix { $symbol:ident | = $value:expr } => {
($symbol == null ? $symbol = $value : $symbol)
}
rule infix { $left:ident | ? $right:expr } => {
(function (left, right) {
return left === null ? right : left;
}(guard $left, $right))
}
rule infix { $left:expr | ? $right:expr } => {
(function (left, right) {
return left == null ? right : left;
}($left, $right))
}
rule infix { $cond:expr | $then:expr : $else:expr } => {
($cond ? $then : $else)
}
rule infix { $operand:ident | } => {
(guard $operand)
}
rule infix { $operand:expr | } => {
($operand != null)
}
}
export ?;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment