gavr123456789 / Niva

Smalltalk like programming language
https://gavr123456789.github.io/niva-site
31 stars 2 forks source link

Need design: static type builders #84

Closed gavr123456789 closed 1 month ago

gavr123456789 commented 9 months ago

Card [ //this here is Card ]

There must be a way to define default action with each expression So this would create append for "a"

But then how to call messages that return string?

Resolver can solve this, if message returns the correct type, and its return not used, then it will be inserted in append. For example + here:

buildString [
  "a"
  "b"
  "Hello" + " World!"
]
gavr123456789 commented 8 months ago

How to handle different this?

foo [ obj1 -> 
  bar [ obj2 ->
    obj2 sas
    obj2 sus
  ]
]

This will look great with cascade

foo [obj1 -> 
  bar [obj2 -> 
    obj2 call;
        call; call; to: obj1
  ]
]

Otherwise:

// foo has call
// bar has call2
foo [ 
  bar [
       .call; call
       .call2

       this@bar call2 call2 // if both have call2
  ]
]
gavr123456789 commented 8 months ago

Builder Declaration:
just usual method declaration but with builder

type Person name: String
// with other params
builder Person x::Int Html.someLambda::[] = [
  html = Html new
  html someLambda do
]
gavr123456789 commented 8 months ago

Builder is always one word, and all other params are like lambda params inline fun Card(modifier: Modifier, lambda: () -> Unit) {} ==

modifier = Modifier width: 5
Card [modifier: modifier -> ...]
gavr123456789 commented 8 months ago

Also 2 [] [] in a row can be used somehow, like in Ocalm

gavr123456789 commented 8 months ago

Static builder... maybe

Person [name: "sas"]

better inheritance syntax? type Person x: Int :+ MegaPerson [ methods declared here is overriding ]

gavr123456789 commented 8 months ago

last design

builder Person buildPerson = [
  this = Person name: "Васёк"
]

buildPerson [ this name is Васёк already ]
builder StringBulder buildStr = [
  defaultAction = [
    this append: it + "\n"
  ]
]

x = buildStr [ 
  "sas"
  "sus"
  "sos"
]
gavr123456789 commented 8 months ago
// fun buildString(builderAction: StringBuilder.() -> Unit): String
builder StringBuilder buildString::[ -> Unit] -> String = [
    init = StringBuilder new
    default::String = [
        init append: it
    ]
    // это произойдет автоматически
    init buildString
    ^ init toString
]

x = buildString [
    "a"
    "b"
    "c"
]
fun buildString(builderAction: StringBuilder.() -> Unit): String {
    val init = StringBuilder()

    // перегружается + для String

    init.builderAction
    return init.toString()
}

val x = buildString {
    // для всех стрингов добавляется перегруженный +
    +"a"
    +"b"
    +"c"
}
gavr123456789 commented 8 months ago

Builder could has a receiver

builder StringBulder buildStr = []
strBuilder buildStr [...]
gavr123456789 commented 8 months ago
html {
    head {
        this@html.head { } // possible
    }
    // ...
}
html [ ht -> 
  head [head -> 
    head // this@html.head
  ]
]
gavr123456789 commented 8 months ago
// builder with receiver
builder StringBuilder build = [
  //default = String
  action = [default::String -> this append: default |> append: "\n" ]
]

b = StringBuilder new
b build [
  "sas"
  "sus"
] 

// builder without receiver

builder buildString = [
  b = StringBuilder new
  action = [ default::String ->
     b append: it
  ]
]

// builder with args
builder StringBuilder build::Int = [...]
build: 423 [...] //  IMPOSSIBLE, same reasons why no top level kw call without this

builder StringBuilder build1::Int ras::String = [...]
build: 423 ras: "sas" [...]

// real builder with arguments
builder StringBuilder buildString build::Int = [...]
buildString [build: 5] [
   ...
]
// or ()
buildString (build: 5) [
   ...
]
// or inside
buildString [ build: 5 ->
   ...
]

// inside wins

Intersection

Just use locals lol!

buildString [
  "Sas"
  "Sus"
  // better
  x = this
  buildString [
    "efe"
    // need to call external
    @this@buildString // nope
    x 
  ]

]
gavr123456789 commented 7 months ago

make unnessesssarry expressions a warnings, maybe

buildString [ "sas" // good 42 // warning ] not to make a soft errors where user things that something is going to happen, but it isnt

gavr123456789 commented 3 months ago

add arguments to builder

a: b: [] problem

if we add it like this, then we have the same problem why we cant make kw calls without this

person name: "qffw" age: 123123
this: 1 is: 2 builder: 3 [
  ...
]

no way to distinguish this

args inside []

kek [arg1: 1 arg2: "Srs" ->

]

args outside

{arg1: 1 arg2: "rrs"} buildSas [

]

probably best option, but still weird, also we kinda dont need args at all, I think, since default action is a way to put any amount of args

gavr123456789 commented 3 months ago
@Composable
inline fun Column(
    modifier: Modifier = Modifier,
    verticalArrangement: Arrangement.Vertical = Arrangement.Top,
    horizontalAlignment: Alignment.Horizontal = Alignment.Start,
    content: @Composable ColumnScope.() -> Unit
) {
    val measurePolicy = columnMeasurePolicy(verticalArrangement, horizontalAlignment)
    Layout(
        content = { ColumnScopeInstance.content() },
        measurePolicy = measurePolicy,
        modifier = modifier
    )
}

2 type of builders maybe

// builder with receiver requiroment
builder Column a::T b::T -> Column= []

Column a: 1 b: 2 [...]

// no receiver
// infer arg for kotlins lambda receiver from return type
builder listOf -> List::T = []

listOf [1 2 3]
gavr123456789 commented 2 months ago

Also maybe its possible to combine both builder with args and without in one, if args will be after body lol

card [
  ...
] width: 30 height: 25

And whats the problem to make them after first word? In Kotlin we still got function name AND arguments, so

card width: 30 height: 25 [
  ...
] 
gavr123456789 commented 2 months ago
card width: (buildWidth from: 4 do []) height: 25 do [
  ...
] 
// but do is unary msg for eval lambdas
lambda = [1 + 2]
// do we send a lambda or we eval it? if there a [ after do then its 100% builder
card width: lambda do [
  ...
]
// and this would mean eval and buildr
card width: lambda do do [
  ...
]
gavr123456789 commented 1 month ago

Lol finally done!