Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Track Issue for HNM Grammar #2

Open
HoshinoTented opened this issue Aug 10, 2020 · 86 comments
Open

Track Issue for HNM Grammar #2

HoshinoTented opened this issue Aug 10, 2020 · 86 comments

Comments

@HoshinoTented
Copy link
Collaborator

HoshinoTented commented Aug 10, 2020

Comment:

** single-line comment
(*
  multi-line comment
*)

Magic (or Function):

magic magic_name_with_an_optional_? [copy_arg: i32; ref_arg: ~i32] {
** `magic` can be replaced with `mag`
    ** Function Body
}: ReturnType

Box Sugar Statement (or Let Statement):

box i: i32 <- init_value.       ** '.' is IMPORTANT
**  ^~~^ Optional Explicit Type Declaration
box ref_i: ~i32 <- ~i.
** Get a reference of i by '~' operator
box j: i32 <- `ref_i.
** deref

Some Key Words:

Ja ** means True
Nein ** means False
logic ** means bool
i32 ** means... i32
lang ** means String
letter ** means char

Member Call:

box s: lang <- "qwq?n".
s->to_lower_case[]

Area Import (or Module Import):

area a->b->c

Crash (or Panic/Throw):

area natural.

magic center [] {
    natural->crash["This Magic Crashed QAQ."].
}

SenTakuShi (or If Statement/Expr):

do (Ja)? {
   when Condition is Ja
} or {
   when Condition is not Ja
}

Repeat SenTakuShi (or Loop):

area natural->world.

do (Ja) /* loop FOREVERRRRRRRRRR */ {
    world->emit["Hello, world!"].
}

^2:

box i <- 2.       ** which is i32
box j <- ! i.      ** `!` is a sugar that means `i * i`

null keyword:

box i: i32 <- null.       ** compile error: null: null is not allowed everywhere.

data structure definition

box point [] {  ** [] can be omitted
    x: i32,
    y: i32
}.

box ptr: point <- point { 2, y: 5 }.

anonymous data structure

box { inner: i32 } foo <- box { 123 }.

sequence (aka array)

magic new_sequence[seq: *i32] {
    seq
}: *i32.

magic center[] {
    ** argument list with separator ','  is treated as Variable Parameter
    box seq: *i32 <- new_sequence[1, 2, 3].

    natural->emit[sequence->length[~seq]].   ** output 3
}.
@chuigda
Copy link

chuigda commented Aug 11, 2020

What will we use for array subscription operation if we use brackets for function call?

@HoshinoTented
Copy link
Collaborator Author

HoshinoTented commented Aug 11, 2020

It may be...:

area natural->arr.   ** I don't think the constructor name will be 'arr'

/* -- snip -- */

arr[1, 2, 3].        ** Like this?

@HoshinoTented
Copy link
Collaborator Author

Wait... What is "array subscription operation"? Get the nth element of an array?

I think we can make an array as a Magic (?, but I don't know how to impl it yet... It may be more complex...)

@chuigda
Copy link

chuigda commented Aug 11, 2020

Wait... What is "array subscription operation"? Get the nth element of an array?

just like in C

int array[] = {1926, 0817};
printf("%d", array[1]);

Java das not have a sugar like [], so we have to use methods like get(). In my opinion at least we should provide some kinds of syntactic sugar for such operations.

@chuigda
Copy link

chuigda commented Aug 11, 2020

I think we can make an array as a Magic

а на функщин, как на функщин. As far as I know, function or magic can act as some mutable data object except in JavaScript.

@HoshinoTented
Copy link
Collaborator Author

HoshinoTented commented Aug 11, 2020

So I think... It may...:

area natural->arr.

box array <- arr[1, 2, 3].
box first <- array[0].

like this?

In this code, array is a magic.
It has some overloaded magic...
maybe...

@HoshinoTented
Copy link
Collaborator Author

HoshinoTented commented Aug 11, 2020

But I didn't come out with what is the array type looks like yet... And this problem may be too hard for me.

@chuigda
Copy link

chuigda commented Aug 11, 2020

So I think... It may...:

area natural->arr;

box array <- arr[1, 2, 3];
box first <- array[0];

like this?

So the idea is to make a "builder" or "constructor" function return an array. So, is the array a value type or reference type?

@HoshinoTented
Copy link
Collaborator Author

HoshinoTented commented Aug 11, 2020

So, is the array a value type or reference type?

It will be a value type, can be copied easily.
Although this design is not common in the modern programming language

@chuigda
Copy link

chuigda commented Aug 11, 2020

But I didn't come out what is the array type looks like yet

Japanese “アレイ(arei)” is just the pronunciation of English “array”。I suggest using “Massiv” (русский:массив)。

@chuigda
Copy link

chuigda commented Aug 11, 2020

It will be a value type, can be copied easily.

Then it will be really hard to return an array from a function, just think about the array in C , std::array in C++,and [T; n] in Rust.

@HoshinoTented
Copy link
Collaborator Author

I may not create a new type of keyword for array...

@HoshinoTented
Copy link
Collaborator Author

Then it will be really hard to return an array from a function

Why?

@chuigda
Copy link

chuigda commented Aug 11, 2020

Then it will be really hard to return an array from a function

Why?

First of all, returning a value from a function involves copying the value from the stack frame of the callee to the stack frame of caller, which will be inefficient without RVO. What's more, values on stack are usually required to have fixed size, which will further limit the utility of array.

@HoshinoTented
Copy link
Collaborator Author

QAQ
That's bad

@HoshinoTented
Copy link
Collaborator Author

Well, so array must be a reference type

@HoshinoTented
Copy link
Collaborator Author

but I think, the MaHouTsukai can:

magic return_array [] {
    ** do something
}: ~ <array type>   ** it returns a reference

@chuigda
Copy link

chuigda commented Aug 11, 2020

but I think, the MaHouTsukai can:

magic return_array [] {
    ** do something
}: ~ <array type>   ** it returns a reference

Then you will need to extend lifetime of the array being returned, by moving it to heap area. And the caller in fact gets a reference~ <array type> instead of a value <array type>.

@HoshinoTented
Copy link
Collaborator Author

array may be allocated at stack?
IDK, what is the behavior of JVM about this?

@chuigda
Copy link

chuigda commented Aug 11, 2020

array may be allocated at stack?
IDK, what is the behavior of JVM about this?

According to Oracle doc:

In the Java programming language, arrays are objects (§4.3.1), are dynamically created, and may be assigned to variables of type Object (§4.3.2). All methods of class Object may be invoked on an array.

Arrays are just Objects, which are created on heap.

@HoshinoTented
Copy link
Collaborator Author

Arrays are just Objects, which are created on heap.

My guess is right.

@HoshinoTented
Copy link
Collaborator Author

Designing a programming language is TOO DIFFICULT!

@HoshinoTented
Copy link
Collaborator Author

HoshinoTented commented Aug 11, 2020

How about this kind of magic calling? :

foo[1, 2, 3; 4, 5, 6; 7].
** `1, 2, 3` is the first argument which is vararg, ';' separates two arguments, `4, 5, 6` is the second argument, `7` is the third argument

This makes vararg can be anywhere, not only at the last parameter.

@chuigda
Copy link

chuigda commented Aug 11, 2020

How about this kind of magic calling? :

foo[1, 2, 3; 4, 5, 6; 7].
** `1, 2, 3` is the first argument which is vararg, ';' separates two arguments, `4, 5, 6` is the second argument, `7` is the third argument

This makes vararg can be anywhere, not only at the last parameter.

Looks all fine but one thing: how does the callee's parameter list look like, and how will callee utilize these varargs?

@HoshinoTented
Copy link
Collaborator Author

"I found it!"

We can use <type>* to represent array type.

@HoshinoTented
Copy link
Collaborator Author

HoshinoTented commented Aug 11, 2020

"I found it!"

We can use <type>* to represent array type.

Well... it will fall into left-recursion...
How about *<type> ?

@HoshinoTented
Copy link
Collaborator Author

* means zero or many, not a pointer. BUT array is a pointer in C or C++!

@HoshinoTented
Copy link
Collaborator Author

Revert to <type>* version.

@chuigda
Copy link

chuigda commented Nov 25, 2021

How do we make capture?

@HoshinoTented
Copy link
Collaborator Author

:( idk

@chuigda
Copy link

chuigda commented Nov 25, 2021

maybe

[=, &a, &b](c: i32, d: i32) -> i32 { a + b + c + d + e }

(the C++ way)


However, since HNM may exploit a reference model, implying that there won't be different ways to capture a variable, the captures can be automatically deduced by compiler (like Java or JavaScript). Thus the explicit capture syntax is not necessary.

@HoshinoTented
Copy link
Collaborator Author

fuck c++

@HoshinoTented
Copy link
Collaborator Author

HoshinoTented commented Dec 14, 2021

data structure grammar: box.

When we declare a variable using box:

box foo: i32 <- 123.
box bar: i32 <- foo + 1.

It does this things:

box {
    inner : i32
} foo <- box { 123 }.  ** constructor grammar might not be the final version
box bar: i32 <- foo->inner + 1.

@HoshinoTented
Copy link
Collaborator Author

HoshinoTented commented Dec 14, 2021

declaring a data structure:

box {
    field0: field_type0,
    field1: field_type1
}: type_name.

after that, use this type:

box foo: type_name <- ???.   ** use box sugar
type_name foo <- ???.          ** use type_name

@HoshinoTented
Copy link
Collaborator Author

HoshinoTented commented Dec 15, 2021

construct a structure:

box { inner: i32 } foo <- box { 123 }.  ** construct value with a anonymous type
lang uncheck <- box { 456 }. ** construct value with type 'lang', without type checking
lang uncheck_but_success <- box { "unchecked construct..." }. ** construct value with type 'lang', without type checking
lang checked <- lang { "checked construct!" }.  ** construct value with type 'lang', with type checking

Unchecked Construct is unsafe, it just wraps some magic bits into one box, without any layout checking.
The compiler may give you some warnings, but it won't cause the compilation to fail.

@HoshinoTented
Copy link
Collaborator Author

using field:

As you see above, we can use an -> operator to use a field.

box { inner: i32 } foo <- box { 123 }.
box bar: i32 <- foo->inner + 123.

@HoshinoTented
Copy link
Collaborator Author

HoshinoTented commented Dec 15, 2021

About math operators and bit operators:
...

All operators may have their context, including ->, ~ and `

~ and ` are in Reference Context, and -> is in Pointing Context.

So:

box { inner: i32 } foo <- box { 123 }.
box ambiguous: i32 <- ~foo->inner.  ** error
box not_ambiguous0: ~i32 <- (~foo)->inner.
box not_ambiguous1: ~i32 <- ~(foo->inner).

@HoshinoTented
Copy link
Collaborator Author

HoshinoTented commented Dec 15, 2021

I don't know what does type parameter list look like, it must be friendly for type infering (omit type parameter purpose)

@HoshinoTented
Copy link
Collaborator Author

Notice

I want something likes Annotation, but I also want to jump out the traditional grammar.
I have to know what does Annotation is...

@HoshinoTented
Copy link
Collaborator Author

In the magic world, the notice doesn't exist in code but exists in the human mind. So IMO, Notice, or Annotation should exist
in another source file.

@HoshinoTented
Copy link
Collaborator Author

HoshinoTented commented Dec 17, 2021

However, it is very inconvenient. I need another solution.

@HoshinoTented
Copy link
Collaborator Author

HoshinoTented commented Dec 17, 2021

we use the> ... < operator to attach Notice (or its new name Tag) to something:

** _ tag marks this magic that is unsafe.
>_< magic unsafe_magic[] { 
    ** body
}.

tag with some additional messages:

>some_tag { "foo" }<
magic some_magic[] {
    ** body
}.

declaring a new Tag

tag new_tag { inner: lang }.

just replaced struct with tag

@HoshinoTented
Copy link
Collaborator Author

HNM must provide tailing recursive, the same as scala, HNM doesn't provide break or continue like.

@HoshinoTented
Copy link
Collaborator Author

HNM must provide tailing recursive, the same as scala, HNM doesn't provide break or continue like.

I want to impl one by myself.

@HoshinoTented
Copy link
Collaborator Author

HoshinoTented commented Dec 18, 2021

like:

box sum: <function type which i never considered before> <- [a: i32, b: i32] -> { a + b }: i32.

function type will be written in:

box f: [type_of_param0; type_of_param1; type_of_param2 ...] -> return_type <- [a; b; c] -> { ... }. 
** no need to specify the return type at the end of lambda.

@HoshinoTented
Copy link
Collaborator Author

Tag s in Standard Magic Dictionary:

  • _: marks something is unsafe, however, the caller can use it without a compilation error
  • x: marks something was deprecated.
  • builder: marks the default constructor as unsafe, and automatically generates a magic that constructs it.
  • gmc1: Rule 1 in Global MaHouTsukai Convention, all fields should not expose to the caller.
    So this tag marks all fields in this box as unsafe, and automatically generates magics that get and set values.

@HoshinoTented
Copy link
Collaborator Author

However, the grammar of HNM is not friendly for curring, we still need to support curring natively.

magic plus[a: i32; b: i32] {
    a + b
}: i32.

magic center[] {
    box plus_one: [i32] -> i32 <- plus[1].

    natural->emit[plus_one[2]].  ** prints 3
}.

@HoshinoTented
Copy link
Collaborator Author

However, the grammar of HNM is not friendly for curring, we still need to support curring natively.

magic plus[a: i32; b: i32] {
    a + b
}: i32.

magic center[] {
    box plus_one: [i32] -> i32 <- plus[1].

    natural->emit[plus_one[2]].  ** prints 3
}.

it will increase binary size...

@HoshinoTented
Copy link
Collaborator Author

... HNM doesn't provide break or continue like.

or not...

I want a feature that can return value from a loop:

box arr: *i32 <- new_sequence[1, 2, 3, 4, 5].
box next_even: i32 <- do {
    box value: i32 <- next_value_of_arr[].
    do (is_even[value]) {    ** if the value is even
        <some keyword> value.
    }
}.

The loop in this code will run 2 times:

  • value == 1: 1 is odd, so continue.
  • value == 2: 2 is even, use this value as the result of the loop.

So next_even should be 2.

@HoshinoTented
Copy link
Collaborator Author

ADT or sealed class:

set option t {    ** a set of types, with a type parameter t
    ** option can be used in the type declaration in here, and only here.

    box {
        tag: option t,    ** a type tag, must be omitted when constructing. one type can only have one type tag with any valid name.
        value: t
    }: some t.

    box {
        tag: option <bottom type>
    }: nothing.
}.

** constructing
magic foo[] {
    box something: option i32 <- box { 123 }: some i32.  ** compiler doesn't know which type you will construct, because option is a set of types
    ** 'tag' cannot appear in constructing
    box otherthing: option i32 <- nothing.    ** sugar of: box {}: nothing
}.

and now, we can use the Pattern Matching operator:

box something: option i32 <- black_box[].

match (something) {
    nothing -> {    ** sugar of: box{}: nothing
        ** do other thing
    }

    box { value_in_some } -> {    ** sugar of: box { value: value_in_some }: some. because the compiler knows that there is the only one possibility.
        ** do some thing
    }
}.

@HoshinoTented
Copy link
Collaborator Author

HoshinoTented commented Jan 13, 2022

I don't think the sealed class syntax is a good design, because some and nothing is a type here.
And the type parameter grammar is also terrible.

@HoshinoTented
Copy link
Collaborator Author

I need a feature that allows the specific parameter is lazy without lambda syntax, for example (Java):

String producer() {
    System.out.println("Halo");
}

String foo(lazy Callable<String> bar) {
    System.out.println("olaH");
    return bar.call();
}

void main(String[] args) {
    foo(producer());
}

it prints:

olaH
Halo

it should be the same as:

String producer() {
    System.out.println("Halo");
}

String foo(Callable<String> bar) {
    System.out.println("olaH");
    return bar.call();
}

void main(String[] args) {
    foo(() -> producer());
}

@HoshinoTented
Copy link
Collaborator Author

Haskell has a nice design about Type Parameter, it also needn't declaration. But this depends on the Naming Style:
Types are starting with an upper letter, and Type Parameters are starting with a lower letter.

But Types are starting with a lower letter in HNM.
However, we may be able to use a special letter to mark a symbol which is a type parameter.

@HoshinoTented
Copy link
Collaborator Author

HoshinoTented commented Apr 20, 2022

We are rarely using parentheses, but it is beauty...

@HoshinoTented
Copy link
Collaborator Author

How about determining the priority by counting the spaces between the operators and operands?
Like: 1 * 2+3 is equivalent to 1 * (2 + 3), 1*2 + 3 is equivalent to (1 * 2) + 3. I know this is not a good idea, but it is fun in some way...

@chuigda
Copy link

chuigda commented Aug 13, 2022

How about determining the priority by counting the spaces between the operators and operands? Like: 1 * 2+3 is equivalent to 1 * (2 + 3), 1*2 + 3 is equivalent to (1 * 2) + 3. I know this is not a good idea, but it is fun in some way...

From the point of implementation, this would require a lexer which is able to read syntax trivia. Then parser will read these syntax trivia and determine precedence. I roughly knows how to write such a lexer/parser.

@HoshinoTented
Copy link
Collaborator Author

construct a structure:

box { inner: i32 } foo <- box { 123 }.  ** construct value with a anonymous type
lang uncheck <- box { 456 }. ** construct value with type 'lang', without type checking
lang uncheck_but_success <- box { "unchecked construct..." }. ** construct value with type 'lang', without type checking
lang checked <- lang { "checked construct!" }.  ** construct value with type 'lang', with type checking

Unchecked Construct is unsafe, it just wraps some magic bits into one box, without any layout checking. The compiler may give you some warnings, but it won't cause the compilation to fail.

Disallowed Unchecked Constructor, it violated the type rules.

@HoshinoTented
Copy link
Collaborator Author

I had a super good idea but I forgot...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants