Git Product home page Git Product logo

nfun's People

Contributors

ericwu91 avatar ingerdev avatar natshep avatar tmteam avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

nfun's Issues

Support optional type

type optional-- : T | none

  1. assume we have 'none' constant of type 'NONE'
  2. optional type T is type that can be either T or NONE
  3. T can be converted to optional--
  4. default of optional-- equals 'none'
    optional:
  5. 'any' is nullable by its nature (???)
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

Replace X**1, x**2, x**3 with x, x*x and x*x*x respectively

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

Create BigInt type

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)

  • type system
  • operators
  • clr convertion
  • syntax settings for bigint
  • specification

Caching of input and output types in Funny.Api

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

Local variables

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

Generic type alias syntax

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
  • to have two syntaxes - is not very consistent. May be implemented in future
  • x[of int].foo() === (x of int).foo()
#' 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

  • default of T === default:T
  • conflicts with slice operator [:step]
  • a = x:int + x:uint - it is confusing
  • most intuitive for a:b reasons (but has some issues, like a = x:int + x:uint)
  • fooof T :T is nice
    -+ a:array[of int] is special...
  • [] is easier to type
#'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 

  • conflicts with slice operator [:step]
  • default:T === default{of T}
  • a = x:int + x:uint - it is confusing
  • most intuitive for a:b reasons (but has some issues, like a = x:int + x:uint)
  • foo(42) :T is nice. better than foo of syntax
  • a:array{of int} is intuitive for C-like. 'of' adds readability
  • very precise for complex notation before fun def
#'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

  • conflicts with slice operator [:step]
  • default:int === default of
  • a = x:int + x:uint - it is confusing
  • most intuitive for a:b reasons (but has some issues, like a = x:int + x:uint)
  • foo of(42) :T is nice
    -+ a:array of is intuitive for C-like
  • foo of ... is generally confusing because of spaces (spaces are not in nfun meta)
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

  • conflicts with slice operator [:step]
  • default:int === default of int
  • a = x:int + x:uint - it is confusing
  • most intuitive for a:b reasons (but has some issues, like a = x:int + x:uint)
  • foo(42) of T :T is quite confusing. May be foo(42) {of int}?
    +- foo(42) of T\r\n :T = is readable
#'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
  • mess in convert /case
#'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]
  • default:int === default
  • conflicts with slice operator [:step]
  • denies chain compare
  • a = x:int + x:uint - it is confusing
  • default:int === default
  • most intuitive for a:b reasons (but has some issues, like a = x:int + x:uint)
  • kotlin way :)
#'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 

  • conflicts with slice operator [:step]
  • a = x:int + x:uint - it is confusing
  • most intuitive for a:b reasons (but has some issues, like a = x:int + x:uint)
  • foo(42) :T is nice. better than foo of syntax
  • a:array{of int} is intuitive for C-like. 'of' adds readability
  • very precise for complex notation before fun def
  • ugly for {of {of int} optional} array
#'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

  • conflicts with slice operator [:step]
  • a = x:int + x:uint - it is confusing
  • most intuitive for a:b reasons (but has some issues, like a = x:int + x:uint)
  • foo of int(42) is quite confusing. May be foo(42) of int?
  • foo of T1, T2(42) is hell
  • foo of T1, T2(i:int) is bloody hell
#'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

  • ok, i try
#'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
  • is not better than a of[b]
  • absolute mess in convert/cast cases
#'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

  • bad idea as it intesects with array access syntax
#'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

  • it crushes my eyes
#'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
  • it crushes both of my eyes
#'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

Generic argument syntax

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)

Incremental type interface

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

Allow partial output struct initialization

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}  #???

Api

Current api is hell

Need to make a new one

Allow to add client-type

client type:

  1. It has alias
  2. it can be converted to any
  3. it has "to text" operation
  4. has default non null value (or has new() constructor)
Funny.WithCustomType<SomeCustomType>("my_type", new SomeCustomType())
a: my_type = if(true) input else default

Support 'return' keyword

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
" )

Map mode

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

Add MultipleStringTemplateCalculator to calculate several strings at once

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.

[] for empty generic array

'[]' equals to 'default', but with array constains

f(a) = if (true) a else [] #so f returns some array

Trailing comma. Allow to complete the enumeration with a comma.

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',
    
    ]
    This beats the more confusing multi-line diff when the trailing comma was omitted:
  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
]

Support struct types

# 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
}

Comparison chain a<b<c

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)...

Char literals support

a:char = /'c'
t:text = [/'h', /'i', /' ']
g:text = [/'a'../'z']
m:text = [1..10].map(rule it.toChar())

Extend `char` support

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[]

SuperAnonymous Rule with more than one arguments fails in scenario with hight order functions

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)]

Support `ip` type

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  <----|
  • Ip type alias
  • Ip type inference
  • Ip from bytes
  • ip from byte[]
  • Convert
  • parse ip constant
  • fluent api
  • ctor
  • default

Support default value for all types and 'default' operator

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

Special operators support π √ ≤ ∑ || && etc

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:

image

Intelij:

image

  • π
  • (+) (-) (*)

Tupple type

y:(int,text) = (42,'vasa')

f(x) = (x*2, x.toText(), x-1)

(g,t,i) = f(42)
  • Type definition: ($type1, $type2 ...)
  • No less than 2 types
  • Can be converted to 'Any'
  • Covariance (?)

Calculate last common ancestor for complex and primitive type

out = [[1],true]

expected: out: any
actual: Runtime error. Unable to cast from Real[] to Bool

  • workaround: deny such casts for a while
  • allow composite type as constraint descendant
  • array fits
  • array lca
  • array max type
  • arrays
  • Support Comparables (6380 passed)
  • fun lca (6427 passed)
  • fun Fits (6444 passed)
  • fun max type
  • funs
  • struct fits
  • struct lca
  • struct max type
  • structs
  • Test for lca of funs, that handles funs as arguments
  • Test for lca of funs, that handles arrays as arguments
  • Test for lca of arrays that handle funs as arguments
  • misc
  • benchmarks

Type aliases

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()

Nullable types support

Following semantics and syntax is not final:

  1. assume we have 'none' constant of type 'NONE'
  2. nullable type T is type that can be either T or NONE
  3. T can be converted to T?
  4. default of T? equals 'none'

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

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.