tmteam / nfun Goto Github PK
View Code? Open in Web Editor NEWExpressions Evaluator for .NET
License: MIT License
Expressions Evaluator for .NET
License: MIT License
2a === 2*a
3.1b === 3.1*b #deny it?
0x === 0*x #deny it?
but 0x1 - is a hex number!
#allow to skip it before lparenth
y = 0.03(12+x) - 0.02x
Allow to specify generic constrains:
a: array[int] # === int[]
b: tupple[int,int] === (int,int)
c: optional[int]
m: fun[int,int,real]
function(a,b) = a+b
r = function[int](1,2)
a:ip = '127.0.0.1'
b:char = 'c'
If constant cannot be parsed - then we may throw FPE
y:(int,text) = (42,'vasa')
f(x) = (x*2, x.toText(), x-1)
(g,t,i) = f(42)
x = a // 2 # '//' - int div operator for [uint8.. int96]
Current api is hell
Need to make a new one
a:char = /'c'
t:text = [/'h', /'i', /' ']
g:text = [/'a'../'z']
m:text = [1..10].map(rule it.toChar())
Failed:
[TestCase("foo() = (rule it1*it2); y = foo()(2,4)",8)]
[TestCase("foo() = rule it1*it2; y = foo()(2,4)",8)]
[TestCase("foo() = rule it1*it2; x = foo(); y = x(2,4)",8)]
[TestCase("foo() = (rule it1+it2+it3); y = foo()(2,3,4)",9)]
[TestCase("foo() = rule it1+it2+it3; y = foo()(2,3,4)",9)]
[TestCase("foo() = (rule it1+it2+it3); x = foo(); y = x(2,3,4)",9)]
[TestCase("x = (rule it1*it2); y = x(2,4)",8)]
[TestCase("x = rule it1*it2; y = x(2,4)",8)]
[TestCase("x = (rule it1+it2+it3); y = x(2,3,4)",9)]
[TestCase("x = rule it1+it2+it3; y = x(2,3,4)",9)]
[TestCase("x = (rule it1); y = x(2)",2)]
[TestCase("x = rule it1; y = x(2)",2)]
[TestCase("y = (rule it1)(2)",2)]
[TestCase("y = (rule it1)(2)",2)]
passed:
[TestCase("x = (rule it); y = x(2)",2)]
[TestCase("x = rule it; y = x(2)",2)]
[TestCase("y = (rule it)(2)",2)]
[TestCase("y = (rule it)(2)",2)]
For arrays, structs, and function calls
this code has to be valid:
i = f(a,b,c,)
j = [a,b,c,]
k = {name = 'vasa', id = 123,}
Motivation: https://stackoverflow.com/questions/11597901/why-are-trailing-commas-allowed-in-a-list
The main advantages are that it makes multi-line lists easier to edit and that it reduces clutter in diffs.
Changing:
s = ['manny',
'mo',
'jack',
]
to:
s = ['manny',
'mo',
'jack',
'roger',
]
involves only a one-line change in the diff:
s = ['manny',
'mo',
'jack',
'roger',
s = ['manny',
'mo',
- 'jack'
+ 'jack',
+ 'roger'
]
The latter diff makes it harder to see that only one line was added and that the other line didn't change content.
It also reduces the risk of doing this:
s = ['manny',
'mo',
'jack'
'roger' # Added this line, but forgot to add a comma on the previous line
]
now real means double
or to allow switch it to decimal
client type:
Funny.WithCustomType<SomeCustomType>("my_type", new SomeCustomType())
a: my_type = if(true) input else default
messageA = ' "Beautiful is better than ugly." - Said Tim Peters'
messageB = " 'Beautiful is better than ugly.'. Said Tim Peters"
# old syntax
myFun(a:int, b:int):real = ...
# new syntax:
myFun(a:int, b:int)->real = ...
Old syntax still has to be valid.
class Car{
public int Power {get;set;}
public string Name {get;set;}
public int Year {get;set;}
}
var result = Funny.Calc<Car>("{ power = 120 }");// Name and Year are not initalized
the problem is that if we got two types:
car1: {power:int, name:text, year:int}
car2: {power:int}
then car1
is convertable to car2
but that feature allows to convert car2
to car1
Solution:
make special property 'default' for fields
then, for output struct type we may say that all the fields are has this property:
car3: {@optional power:int,@optional name:text,@optional year:int}
the question is - what is lca for car3, car2?
lca(car3, car2) = {power:int,@optional name:text,@optional year:int} #???
Provide syntax to specify Generic arguments
Add any sintax to the candidate list. Comment any thoughts on any syntaxes
Candidates:
#'a of[b,c]' syntax
#'a:b, a[of b]' syntax
#'a of b, a [of b,c], [of] fun(...)' syntax
#'a:b, a{of b,c}' syntax
#'a:b, a<of b,c>' syntax
#'a:b, a of<b>' syntax
#'a:b, a of b, foo() of b' syntax
#'a<b,c>' syntax
#'a of(b,c)' syntax
#'a:b a<b,c>' syntax
#'a:b a:(b,c)' syntax
#'a()of[b,c]' syntax
#'a of b, a [of b,c], [of] fun(...)' syntax
a:optional of int = default
b = default of optional of int
w: array of optional of int = [1,2,none]
c = foo[of int](42)
c2 = foo(42) of int
d = foo[of optional of int,text](31,'test')
e:array of int = default
f = [1,2,3 of int]
g = [1,2,3] of real[]
h = cast x of int
i = (cast x) of text
j= cast [of int,text] x
k = x[of int].convert()
l = x.convert() of text
m= x.convert of [int,text]()
o = convert(x of[int])
p = convert(x) of[text]
q= convert of [int,text](x)
bar [of T] (a:T): optional of T = if(a==default) none else a
foo [of T1, T2](a:T1):T2 = if (T1>default) T1 else T2
[of T1, T2, where T1,T2 is <> ]
foo (a:T1, b:T2)
= if (T1>T2) T1 else T2
#' a of[b,c]' syntax
a:optional of[int] = default
b = default of[optional of int]
w: array of[optional of[int] = [1,2,none]
c = foo of[int](42)
c2 = of [int] foo(42)
d = foo of[optional of[int],text](31,'test')
e:array of[int] = default
f = [1,2,3 of [int]]
g = [1,2,3] of [real[]]
h = cast x of[int]
i = (cast x) of[text]
j= cast of [int,text] x
k = x of[int].convert()
l = x.convert() of[text]
m= x.convert of [int,text]()
o = convert(x of[int])
p = convert(x) of[text]
q= convert of [int,text](x)
bar of[T] (a:T): optional of[T] = if(a==default) none else a
foo of[T1, T2](a:T1):T2 = if (T1>default) T1 else T2
foo of[T1, T2](a:T1, b:T2) where { T1,T2 is <>}
= if (T1>T2) T1 else T2
#'a:b, a[of b]' syntax
a:optional[of int] = default
b = default:optional[of int]
w: array[of optional[of int]] = [1,2,none]
c = foo[of int](42)
c2 = foo(42):int
d = foo[of optional[of int],text](31,'test')
e:array of int = default
f = [1,2:int, 3 ]
g = [1,2,3]:real[]
h = cast x:int
i = (cast x):text
j= cast[of int,text] x
k = x:int.convert()
l = x.convert():text
m= x.convert[of int,text]()
o = convert(x:int)
p = convert(x):text
q= convert[of int,text](x)
bar[of T](a:T): optional[of T] = if(a==default) none else a
foo[of T1, T2](a:T1) :T2 = if (T1>default) T1 else T2
foo[of T1, T2: T1,T2 is <>](a:T1, b:T2)
= if (T1>T2) T1 else T2
#can be moved upper
[of T1, T2: T1,T2 is <>]
foo(a:T1, b:T2)
= if (T1>T2) T1 else T2
a = x:int + x:uint
)#'a:b, a{of b}' syntax
a:optional{of int} = default
b = default:optional{of int}
w: array {of optional {of int}} = [1,2,none]
c = foo{of int}(42)
c2 = foo(42):int
d = foo{of optional{of int},text}(31,'test')
e:array{of int} = default
f = [1,2:int, 3 ]
g = [1,2,3]:real[]
h = cast x:int
i = (cast x):text
j= cast{of int,text} x
k = x:int.convert()
l = x.convert():text
m= x.convert{of int,text}()
o = convert(x:int)
p = convert(x):text
q= convert{of int,text}(x)
bar{of T}(a:T): optional{of T} = if(a==default) none else a
foo{of T1, T2}(a:T1) :T2 = if (T1>default) T1 else T2
foo{of T1, T2: T1,T2 is <>}(a:T1, b:T2)
= if (T1>T2) T1 else T2
#may move upper
{of T1, T2: T1,T2 is <>}
foo(a:T1, b:T2)
= if (T1>T2) T1 else T2
a = x:int + x:uint
)#'a:b, a of<b>' syntax
a:optional of<int> = default
b = default:optional<of int>
w: array<of optional<of int>> = [1,2,none]
c = foo of<int>(42)
c2 = foo(42):int
d = foo of<optional of<int>,text>(31,'test')
e:array of int = default
f = [1,2:int, 3 ]
g = [1,2,3]:real[]
h = cast x:int
i = (cast x):text
j= cast of <int,text> x
k = x:int.convert()
l = x.convert():text
m= x.convert of<int,text>()
o = convert(x:int)
p = convert(x):text
q= convert of <int,text>(x)
bar of<T>(a:T): optional of<T> = if(a==default) none else a
foo of<T1, T2>(a:T1) :T2 = if (T1>default) T1 else T2
foo of<T1, T2: T1,T2 is <>>(a:T1, b:T2)
= if (T1>T2) T1 else T2
a = x:int + x:uint
)Syntax candidates to solving [a:b] problem
y = [1..4][0 to 3]
z = [1..4][0:int to 3:real step 5]
zz = [1..4][0 to 3 step 5]
yy = [1..4][to 3]
mm = [1..4][1 to]
mm = [1..4][1 to step 5]
y10 = [1..4][0 ... 3 step 5]
z10 = [1..4][0:int ... 3:real step 5]
yy = [1..4][...3]
mm = [1..4][1...]
mm = [1..4][1... step 5]
y3 = [1..4][0 :: 5]
z3 = [1..4][0:int :: 3:real step 5]
i3 = [1..4][:: 5]
f3 = [1..4][0::]
k3 = [1..4][0::step 5]
y5 = [1..4][0---5]
z5 = [1..4][0:int --- 3:real step 5]
i5 = [1..4][---5]
f5 = [1..4][0---]
k5 = [1..4][0--- step 5]
madY = y = [1..4][0..3]
madZ = [1..4][0..3 step 5]
madZ2 = [1..4][0,1,2,3]
wow1 = foo(:int,42) # we may send type here!
foo(t:type, a) = if a.getType() == type "it is" else "it is not"
#'a:b, a of b, foo() of b' syntax
a:optional of int = default
b = default:optional of int
w: array of optional of int = [1,2,none]
c = foo(42) of int
c2 = foo(42):int
d = foo(31,'test') of (optional of int,text)
e:array of int = default
f = [1,2:int, 3 ]
g = [1,2,3]:real[]
h = cast x:int
i = (cast x):text
j= cast x of (int,text)
k = x:int.convert()
l = x.convert():text
m= x.convert() of (int,text)
o = convert(x:int)
p = convert(x):text
q= convert(x) of (int,text)
bar(a:T) of T
: optional of T = if(a==default) none else a
foo(a:T1) of (T1, T2) :T2 = if (T1>default) T1 else T2
foo(a:T1, b:T2) of (T1, T2) { T1,T2 is <>}
:T1 = if (T1>T2) T1 else T2
a = x:int + x:uint
)#'a<b,c>' syntax
a:optional<int> = default
b = default<optional<int>>
c = foo<int>(42)
c2 = foo(42)<int>
d = foo<optional<int>,text>(31,'test')
e:array<int> = default
f = [1,2<int> 3 ]
g = [1,2,3]<real[]>
h = cast x<int>
i = (cast x)<text>
j= cast<int,text> x
k = x<int>.convert()
l = x.convert()<text>
m= x.convert<int,text>()
o = convert(x<int>)
p = convert(x)<text>
q= convert<int,text>(x)
bar<T>(a:T): optional<T> = if(a==default) none else a
foo<T1, T2>(a:T1):T2 = if (T1>default) T1 else T2
foo<T1, T2>(a:T1, b:T2){ T1,T2 is <>}
= if (T1>T2) T1 else T2
denies chain comparation
#'a of(b,c)' syntax
a:optional of(int) = default
b = default of(optional of(int))
w: array of(optional of(int)) = [1,2,none]
c = foo of(int)(42)
c2 = foo(42) of (int)
d = foo of(optional of int,text)(31,'test')
e:array of(int) = default
f = [1,2 of (int), 3 ]
g = [1,2,3] of (real[])
h = cast x of (int)
i = (cast x) of (text)
j= cast of (int,text) x
k = x of(int).convert()
l = x.convert() of(text)
m= x.convert of (int,text)()
o = convert(x of (int)
p = convert(x) of(text)
q= convert of (int,text)(x)
bar of(T)(a:T): optional of(T) = if(a==default) none else a
foo of(T1, T2)(a:T1):T2 = if (T1>default) T1 else T2
foo of(T1, T2)(a:T1, b:T2){ T1,T2 is <>}
= if (T1>T2) T1 else T2
#'a:b a<b,c>' syntax
a:optional<int> = default
b = default:optional<int>
w: array<optional<int>> = [1,2,none]
c = foo<int>(42)
c2 = foo(42):int
d = foo:optional<int,text>(31,'test')
e:array:int = default
f = [1,2:int, 3 ]
g = [1,2,3]:real[]
h = cast x:int
i = (cast x):text
j= cast<int,text> x
k = x:int.convert()
l = x.convert():text
m= x.convert<int,text>()
o = convert(x:int)
p = convert(x):text
q= convert<int,text>(x)
bar:T(a:T): optional-<T> = if(a==default) none else a
foo:(T1, T2)(a:T1):T2 = if (T1>default) T1 else T2
foo:(T1, T2)(a:T1, b:T2){ T1,T2 is <>}
= if (T1>T2) T1 else T2
y = [1..4][0:3 step 5]
z = [1..4][(0:int):(3:real) step 5]
a = x:int + x:uint
)#'a:b a:(b,c)' syntax
a:optional:int = default
b = default:optional:int
w: array:optional:int = [1,2,none]
c = foo:int(42)
c2 = foo(42):int
d = foo:optional:(int,text)(31,'test')
e:array:int = default
f = [1,2:int, 3 ]
g = [1,2,3]:real[]
h = cast x:int
i = (cast x):text
j= cast:(int,text) x
k = x:int.convert()
l = x.convert():text
m= x.convert:(int,text)()
o = convert(x:int)
p = convert(x):text
q= convert:(int,text)(x)
bar:T(a:T): optional-<T> = if(a==default) none else a
foo:(T1, T2)(a:T1):T2 = if (T1>default) T1 else T2
foo:(T1, T2)(a:T1, b:T2){ T1,T2 is <>}
= if (T1>T2) T1 else T2
y = [1..4][0:3 step 5]
z = [1..4][(0:int):(3:real) step 5]
#'a()of[b,c]' syntax
a:optional of[int] = default
b = default of[optional of int]
w: array of[optional of[int]] = [1,2,none]
c = foo of[int](42)
c2 = foo(42) of int
d = foo of[optional of[int],text](31,'test')
e:array of[int] = default
h = cast x of [int]
i = (cast x) of [text]
j= cast of [int,text] x
k = x of [int].convert()
l = x.convert() of [text]
m= x.convert of [int,text]()
o = convert(x of [int])
p = convert(x) of [text]
q= convert of [int,text](x)
bar(a:T): optional of[T] of [T]
= if(a==default) none else a
foo(a:T1):T2 of [T1, T2]
= if (T1>default) T1 else T2
foo(a:T1, b:T2) of [T1, T2] where { T1,T2 is <>}
= if (T1>T2) T1 else T2
bar(a:T): optional of[T] of [T]
is a mess
not sure:
rejected:
#'a:b, {of b}' syntax
a:{of int}optional = default
b = default:{of int}optional
w:{of {of int} optional} array = [1,2,none]
c = {of int}foo(42)
c2 = foo(42):int
d = {of {of int}optional,text}foo(31,'test')
e:{of int}array = default
f = [1,2:int, 3 ]
g = [1,2,3]:real[]
h = cast x:int
i = (cast x):text
j= {of int,text}cast x
k = x:int.convert()
l = x.convert():text
m= x.{of int,text}convert()
o = convert(x:int)
p = convert(x):text
q= {of int,text}convert(x)
{of T}
bar(a:T): {of T}optional = if(a==default) none else a
foo{of T1, T2}(a:T1) :T2 = if (T1>default) T1 else T2
{of T1, T2: T1,T2 is <>}
foo(a:T1, b:T2)
= if (T1>T2) T1 else T2
a = x:int + x:uint
)#'a:b, a of b' syntax
a:optional of int = default
b = default:optional of int
c = foo of int(42)
c2 = foo(42):int
d = foo:optional:(int,text)(31,'test')
e:array of int = default
f = [1,2:int, 3 ]
g = [1,2,3]:real[]
h = cast x:int
i = (cast x):text
j= cast of (int,text) x
k = x:int.convert()
l = x.convert():text
m= x.convert of [int,text]()
o = convert(x:int)
p = convert(x):text
q= convert of [int,text](x)
bar of T(a:T): optional of T = if(a==default) none else a
foo of T1, T2(a:T1):T2 = if (T1>default) T1 else T2
foo of (T1, T2)(a:T1, b:T2){ T1,T2 is <>}
= if (T1>T2) T1 else T2
a = x:int + x:uint
)#'a-<b a-<(b,c)' syntax
a:optional-<int> = default
b = default-<optional-<int>>
c = foo-<int(42)
c2 = foo(42)-<int
d = foo-<optional-<(int,text)(31,'test')
e:array<int> = default
f = [1,2-<int, 3 ]
g = [1,2,3]-<real[]
h = cast x-<int
i = (cast x)-<text
j= cast-<(int,text) x
k = x-<int.convert()
l = x.convert()-<text
m= x.convert-<(int,text)()
o = convert(x of (int)
p = convert(x) of(text)
q= convert of (int,text)(x)
bar-<T>(a:T): optional-<T> = if(a==default) none else a
foo-<T1, T2>(a:T1):T2 = if (T1>default) T1 else T2
foo-<T1, T2>(a:T1, b:T2){ T1,T2 is <>}
= if (T1>T2) T1 else T2
#'of[b,c] a' syntax
a: of[int] optional = default
b =of[optional of int] default
c = of[int] foo(42)
c2 = of[int] foo(42)
d = of[optional of[int],text] foo(31,'test')
e:of[int] array = default
f = [1,2,of [int] 3 ]
g = of [real[]] [1,2,3]
h = cast of[int] x
i = of[text] cast x
j = # impossible
k = (of[int] x).convert()
l = of[text] x.convert()
m= x.of [int,text] convert()
o = convert(of[int] x)
p = of[text] convert(x)
q= of [int,text] convert(x)
of[T] bar(a:T): of[T] optional = if(a==default) none else a
of[T1, T2] foo(a:T1):T2 = if (T1>default) T1 else T2
of[T1, T2] where { T1,T2 is <>}
foo(a:T1, b:T2)
= if (T1>T2) T1 else T2
a of[b]
#'a[b,c]' syntax
a:optional[int] = default
b = default[optional[int]]
c = foo[int](42)
c2 = foo(42)[int]
d = foo[optional[int],text](31,'test')
e:array[int] = default
f = [1,2[int], 3 ]
g = [1,2,3][real[]]
bar[T](a:T): optional[T] = if(a==default) none else a
foo[T1, T2](a:T1):T2 = if (T1>default) T1 else T2
foo[T1, T2](a:T1, b:T2){ T1,T2 is <>}
= if (T1>T2) T1 else T2
#'a-<b,c>' syntax
a:optional-<int> = default
b = default-<optional-<int>>
c = foo-<int>(42)
d = foo-<optional-<int>,text>(31,'test')
e:array<int> = default
f = [1,2-<int>, 3 ]
g = [1,2,3]-<real[]>
bar-<T>(a:T): optional-<T> = if(a==default) none else a
foo-<T1, T2>(a:T1):T2 = if (T1>default) T1 else T2
foo-<T1, T2>(a:T1, b:T2){ T1,T2 is <>}
= if (T1>T2) T1 else T2
#'a-<b,c>-' syntax
a:optional-<int>- = default
b = default-<optional-<int>->-
c = foo-<int>-(42)
c2 = foo(42)-<int>-
d = foo-<optional-<int>-,text>(31,'test')
e:array<int> = default
f = [1,2-<int>-, 3 ]
g = [1,2,3]-<real[]>-
bar-<T>-(a:T): optional-<T>- = if(a==default) none else a
foo-<T1, T2>-(a:T1):T2 = if (T1>default) T1 else T2
foo-<T1, T2>-(a:T1, b:T2){ T1,T2 is <>}
= if (T1>T2) T1 else T2
#'a of b, a of(b,c)' syntax
a:optional of int = default
b = default of optional of int
c = foo of int(42)
c2 = foo(42) of int
d = foo of(optional of int,text)(31,'test')
e:array of int = default
f = [1,2 of int, 3 ]
g = [1,2,3] of real[]
bar of T (a:T): optional of T = if(a==default) none else a
foo of (T1, T2)(a:T1):T2 = if (T1>default) T1 else T2
foo of (T1, T2)(a:T1, b:T2){ T1,T2 is <>}
= if (T1>T2) T1 else T2
two syntaxes - looks not very consistent. May be implemented in future
a = [1..2 step 1]
a = [100..1] step -1
Here are the candidates for special characters.
Why are they needed? Well, just because it's fun
The only rule is not to harm
#really nice:
ฯ === 3.14...
โ === real.infinity
โ4 === pow(4,0.5)
a โค b === a<= b
a โฅ b === a>= b
a โ b === a !=b
#not sure
a โ b === a in b
a โ b === not( a in b)
a โ b === a.intesect(b)
a โ b === a.distinct(b)
โ[1,2,3] === [1,2,3].sum()
a [*] b === a.repeat(b) # i litterally forgot, what i meant with this.
(+) (-) (*) can be used as array operators or it may be used as overflow operators
1 (+) 2 === 1+2 with overflow support
same for (+) (-) (*) (>>) (<<) (**)
(**) is defined for any non negative intgers (u8<= T<= u64)
a [+] b === a.concat(b)
a [-] b === a.except(b)
[1,2,3] โ rule it>2 === [1,2,3].all(rule it>2)
[1,2,3] โ rule it>2 === [1,2,3].any(rule it>2)
[1,2,3] โ rule it>2 === [1,2,3].all(rule not(it>2))
a = xแตข
m = logโ(th/24)
#bad idea
a โ b === a [+] b === a.concat(b) # very bad symbol in sublime
a โ b === a [-] b === a.except(b) # very bad symbol in sublime
โ[1,2,3] === [1,2,3].fold(1, rule it1*it2)
โ(x+1) === pow(x+1,1/3)
โ(x+1) === pow(x+1, 0.25)
Need to validate in sublime/intelij fonts - to answer "what looks good and what is not"
Sublime:
Intelij:
For example we got some layout in some form
Dashboard text: 'Hello {name}. Current value is {x}'
Button1 text: 'Increase value to {x+1}'
Button2 text: 'Decrease value to {x-1}'
'x' - is shared variable among all three text expression.
It is equal to such nfun script:
d = 'Hello {name}. Current value is {x}'
b1 = 'Increase value to {x+1}'
b2 = 'Decrease value to {x-1}'
Current api does not allow us to share variable 'x' in such a way.
a:ip = 192.168.0.1
localhost = 127.0.0.1
#true
127.0.0.1 in [127.0.0.1 .. 127.0.10.0]
0.0.0.0 == default
implicit:
ip-> any
convert():
long -> ip
ip -> long
ulong -> ip
ip -> ulong
text -> ip
ip -> text
to be discussed
introduce url, ipport types
any <-- url <-- ipport <--ip
or
any <--url<---ipport
| <---ip <----|
byte[]
Funny.BuildForCalcContext<UserContextModel>().ToAction("42") //should throw
'[]' equals to 'default', but with array constains
f(a) = if (true) a else [] #so f returns some array
literal, comparasing, increment
# literal:
a:char = 'a'[0]
b:char = 'z'[0]
# operators:
a<b #true
'x'[0] in [a..b] # true #Excluded. It will be solved in separate task
# functions:
char.toText()
byte.toChar() #Excluded. toXXX functions are not implemented
a.increment().increment() # 'c' #Excluded. It will be solved in separate task
# convert():
text->char
uint->char->uint #Same for every int type
char -> byte[]
Support case, when we have input and output context types
runtime = Fun.Make<InputType,OutputType>(expression)
OutputType result = runtime.Run(new InputType(...));
the case is most common, as we know input and output context in most cases
Cover cases:
f(x) =
m = x*2
m+x -1
sf(a,b,c) =
d = b**2 -4a*c
return
if(d>0)
ย ย ย ย ย ย ย ย (-b+ 2*a, -b- 2*a)
else none
allow to return values from function with 'return' value
f(x) =
m = x**2
return m-1
Allow to return values as output variable form equation
var f = Funny.Calc<double>("
x = 1
y = x*2 + 1
c = x+ y
return c
" )
5%2 == 1 # remainder operator for types [byte..real]
Every time when Nfun searching for convertor between CLR and Nfun type and back - it creates it from the scratch.
It is quite complex operation so it is better to cache convertors for struct types
type user: { name: text, age:int}
type arraa: [int]
type tupka: (int, int, text)
type choice: int | real | text
type funka: fun(int,int)->text
f(x:choice)->user = {...}
m:arraa = [1,2,3]
x:funka = ...
x(1,2).print()
Following semantics and syntax is not final:
optional:
5) 'any' is nullable by its nature (???)
a:any = none
a:optional[int] = none
if is statements:
# a!=none equals to not(a is none).
# It means that 'a' in the if-block looses it's nullability and casts to concrete T
result = if (a != none)
a # a has type of T here
else
0 # a has type of optional[T] here
operators:
result = a?.count()# result: T?
result2 = a??0 #result has type 0
result3:int = a??default
result3 = a?? default # seems like result3 has type of 'T?' here
result4 = a!! #result:T, Error may be thrown
every type has it's default value
f(a,b) =
if (a>b) a
if (b>a) b
else default
default(any) = none # depends on nullability support.
default(int) = 0
default(real) = 0.0
default(bool) = false
default(text) = ""
default( array of t) = [ ]
default {field1, field 2} = { field1 = default, field2 = default}
default rule(T,T):R = rule(T,T):R = default
Nfun:
a = item.bALAnce
Clr-Struct:
class Item{
public int Balance{get;set;}
}
Error:
The given key 'bALAnce' was not present in the dictionary
Signature of the exponentiation function: **(x:real, y:real):real
The signature is as follows, because for integers, negative numbers, it is possible to use a negative degree (which will lead to floating-point numbers), and for unsigned integers, overflow is easily possible.
However, the user expects a record of the type:
y:int = x**2
It will not give errors.
Goal: to allow a record of type y:int = x**2
out = [[1],true]
expected: out: any
actual: Runtime error. Unable to cast from Real[] to Bool
Tupple: (1,2,3): (int,int,int)
Function: rule(x,y)=... : rule(int,int)->int
Structure: {a=.., b=...}: {a:int, b:int}
so sounds reasonable, that array has the same syntax:
a: [int] = [1,2,3]
type optional-- : T | none
use 'none' const and aliasless 'none' type with default value of none
a = none
b = if(a == none) "nothing" else "anything" #nothing
#optional-<T>- type can be converted to any. T can be converted to optional-<T>- type
a = if(true) 42 else none # a is optional-<T>-
b:any = a # is ok
c:int = a # fails
#optional can be used only in if expression
a = if(true) 42 else none
b = if(a==none) default else a+31
c = if(a!=none) a+31 else default
'otherwise' function can be used to return fallback value if the origin value is in fallback
#sketch
otherwise(a, defaultValue) =
if(a == none) defaultValue
else a
#sketch
otherwise(a, defaultValue) =
if(a == none) default
else a.notNone()
#sketch
notNone(a) =
if(a == none) error
else a
# initializator
user is @{
age:int
name:text
size: real
}
# field access
x:user
out = x.age / x.size
# constructors
m = @{
age = 42
name = 'vasa'
size = 15.5
}
# m is generic, it can be converted to user
u:user = m
# @A can be converted to @B if
# - @A contains all fields of @B
# - Every field @A .f of can be converted to @B.f
#it's ok
j:user = @{
age = 42
name = 'vasa'
nick = 'cool
size = 15.5
}
#it is wrong. fun parse exception as name is skipped
h:user = @{
age = 42
nick = 'cool
size = 15.5
}
As char is arithmetic type - it can be used in such an expressions:
word = [/'a'../'c'] #'abc'
ips = [127.0.0.1.. 127.0.0.5] # [127.0.0.1, 127.0.0.2, 127.0.0.3, 127.0.0.4, 127.0.0.5]
range(a,b) = [a..b]
word2 = range(/'a',/'b') #'abc'
range2 = range(1,3) #[1,2,3]
so the arithmetic is inteface:
Incremental<T> <= IComparable<T>:
T Increment(T)
T Decrement(T)
T MaxValue()
T MinValue()
Numbers, chars, days, months, ip and other types has to implement the interface
any
|-----incremental : comaprable
|---------numbers
|---------char
|---------ip
Convertion (int64|uint64)->bigint->real
Operators All arithmetics and bitwise
Id bigint (optional : int)
Clr type BigInteger
Allow to choose prefered integer type for constant and integer operators ( use int as alias for bigint)
Operators, priorities, syntax contructions, type system etc
to study the potential impact on performance if the node does not copy information from tokens, does not store token-range from the lexer
f(a, b, c) = a+b+c
y = f( a = 12, c = 24, b = 13)
#or even
y = f(
a = 12
c = 24
b = 13
)
Simplified syntax for the case when there are several comparison operations connected via And, which involve the same arguments.
# Was
a<b and b<c and c<d
# became
a<b<c<d
Provide support for operations <, >, <=, >=
if(a>b<c) ...
if( a<= b >= c)...
If any struct type has field of Float or Decimal - it has to be converted intro Real and Back
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.