设计一个新的语言-1

由于兴趣原因想设计一个新的语言。这是一个类似C和Go的语言,为了代码简洁简化一些代码,语言内建大量函数,可以直接调用。允许一定程度的指针访问,提供布尔型,数字型,字符串,指针类型,数组类型,结构化类型,函数类型,切片类型。这是一门静态语言,内存管理模型和c一样需要手工管理。接口使用非侵入的duck type模式。

基本数据类型

数字类型

有符号整数

int8 (-128 -> 127)
int16 (-32768 -> 32767)
int32 (-2,147,483,648 -> 2,147,483,647)
int64 (-9,223,372,036,854,775,808 -> 9,223,372,036,854,775,807)
int (32 位操作系统上32位,64 位操作系统64 位)

无符号整数

uint8 (0 -> 255)
uint16 (0 -> 65,535)
uint32 (0 -> 4,294,967,295)
uint64 (0 -> 18,446,744,073,709,551,615)
uint (32位操作系统上32 位,64位操作系统64位)

浮点型

float32 (+- 1.2e-38 -> +- 3.4 * 1e38)
float64 (+- 2.3e-308 -> 1.7e308)
float128(+- 3.5e-4932 -> 1.1e4932)
建议使用float64

复数

complex64 (32 位实数和虚数)
complex128 (64 位实数和虚数)

字符

byte类型

byte类型:等同于uint8,有三种表达式:

1
2
3
byte ch = 'A'
byte ch = 65 //或者byte ch = 0x41
byte ch = '\x41' //字符表达,\x后接两位16进制

rune类型:等同于int32,最少需要int16来储存一个Unicode,两个字节的utf8使用\u前缀,四个字节utf8mb4使用\U来表示。\u紧接四个16进制数,\U紧接八个16进制数。

1
2
3
int ch = '\u0041'
int ch = '\u03B2'
int ch = '\U00101234'

字符串

字符串定义:
struct string
{
byte* str;
int64 len;
}

1
2
3
4
5
string str1 = "This is a string"
str2 := str1 + "Hello World"
// 声明字符串时可以自动根据右边的语句构造一个字符串,但是一个string就是一个原子所以不能像C语言那样用string[x]对第x-1个值进行修改,只能修改地址值,如:
str1 = "This is another string"
// 这样结构体内的str和len值就发生了改变

切片 | slice

相当于Java或者Python中的list,能记录长度和容量,也可以理解成一个滑动窗口,但是slice是引用类型所以使用需要注意不要踩坑。
底层定义:

1
2
3
4
5
type slice struct {
pointer array // pointer是无类型的指针,建议不会用就不要使用,在开发时不应直接使用
int len
int cap
}
1
s1 := []string{""}

循环语句

在for中,去掉(),加入range用法,如:

1
2
3
4
5
6
7
int arr[10]
for int i = 0; i < 10; i++ {
arr[i] = i
}
for index, value := range arr {
printf("index = %d, value = %d", index, value)
}

条件语句

switch默认在句尾加入break,如果需要继续判断下面语句则需要加入fallthrough,如:

1
2
3
4
5
6
7
int i = 90
switch i {
case 90:
printf("等于90")
fallthrough
case 80: printf("等于80")
}

注意:由于switch是需要对类型进行判等操作,case后的无符号的表达式结果可以转换成switch后的表达式的类型,反之switch后的无符号的表达式结果不能转换成case后的表达式结果的类型而是转换成该值的默认类型(比如无类型的123转换成int类型,3.14转换成float64类型),所以想让编译通过也是有条件的,如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
int8 arr[] = {0, 1, 2, 3, 4, 5}
switch 1+2 {
case arr[0], arr[1]:
printf("0 or 1")
case arr[2], arr[3]:
printf("2 or 3")
case arr[4], arr[5]:
printf("4 or 5")
}
// 编译不通过,1+3是无符号类型,转换成默认类型是int,而case后是int8类型
switch arr[3] {
case 0, 1:
printf("0 or 1")
case 2, 3:
printf("2 or 3")
case 4, 5:
printf("4 or 5")
}
// 编译通过,因为case后的无类型值可以转换成int8类型。
// 注意:case后的类型只有在无类型时才能发生类型自动转换

象牙运算符

直接由编译器判断类型,同时声明和定义一个变量,如:

1
2
3
i := 10
str := "string"
arr := {1, 2, 3}

方法

和函数不一样,必须拥有一个接收者,代码操作和接收者绑定,如

1
2
3
int (int i)returnANum() {       // i为接收者,操作与i绑定
return i
}

多返回值

一个函数或者方法可以返回多个值,如:

1
2
3
4
5
6
7
8
9
10
11
(int, float32)returnANum(){
float32 f = 13.14
i = 1
return i, f
}
(string str, int i)(int i)returnAString() {
string str = "This is a string"
return
}
i, f := returnANum() // i=1, f=13.14
str, j := i.returnAString() //str="This is a string", j = 1

多返回值取其中一个

可以在函数或者方法后接.返回值可以只取一个,或者用_来抛弃返回值,如:

1
2
3
// func()返回
max := func(a, b, c).max
sum, _ := func(a, b, c)

单条语句代码换行 (待定)

如果不是双引号的代码可以在逗号后面直接换行,如果是字符串需要多行可以用反单引号或者加号,如:

1
2
3
4
5
6
7
8
9
10
11
12
printf("a = %d, b = %d", 
a, b)

str := `<!DOCTYPE html>
<html lang="en">
<head>
<title>Document</title>
</head>
<body>
</body>
</html>` +
"this is a html5 code"

匿名函数

可以声明一个匿名函数,还可以把他赋值给一个变量,比如:

1
2
3
4
5
6
7
8
func := void {
printf("hello world!")
}
func() // 输出hello world!

void (int x, int y){
printf("sum = %d", x, y)
}(10, 20) // 输出sum = 30

闭包

如:

1
2
3
4
5
6
7
8
9
10
11
12
13
typedef operate int (int, int)      // 定义一个返回值为int,参数列表为两个int值的函数类型
typedef calculate int (int, int)

calculate getSum(op operate) {
return int(int x, int y){
return op(x, y)
}
}
add := int (int x, int y){
return x + y
}
addFunc := getSum(add)
printf("sum = %d", addFunc(10, 20)) // 输出sum=30

包管理和引入

待定

使用结构体代替类

这个得看怎么解决包管理

接口

空接口