5
5
title : 快速开始
6
6
order : -1
7
7
---
8
+
8
9
注意mcfpp语句是以分号结尾的。
9
10
10
11
# 工程信息文件JSON格式
12
+
11
13
工程信息文件置于工程根目录的位置,作为编译器编译的入口,包含了工程的所有信息。
14
+
12
15
``` json
13
16
{
14
17
//工程包含的文件。允许通配符*和相对路径
30
33
```
31
34
32
35
# 通用语法
36
+
33
37
## 变量
38
+
34
39
声明:` type identifier (= expr)?; `
40
+
35
41
例如:` int i = 5 + p; ` ,` int x,y,z; `
42
+
36
43
mcfpp 支持的运算符有` + ` ,` - ` ,` * ` ,` / ` ,` % ` (取余),` && ` ,` || ` ,` ! ` ,` ++ ` ,` -- `
37
44
注意` ++ ` 和` -- ` 只能单独作为一个语句,即只能` i++; ` ,而不能` i = i ++; `
38
45
39
46
mcfpp的基本数据类型有:
47
+
40
48
| 类型名 | 类型描述 | 例子 |
41
49
| -----------| -------------- | ----------- |
42
50
| int | 最基础的类型,表示一个整数 | ` 1 ` ,` 114514 ` ,` -5 ` |
@@ -47,15 +55,23 @@ mcfpp的基本数据类型有:
47
55
| selector | 表示一个目标选择器 | ` @a ` ,` @p[limit=6] ` |
48
56
49
57
### 变量修饰符
58
+
50
59
变量修饰符可以用来表示变量的类型,包括` dynamic ` ,` const ` ,` import `
60
+
51
61
- dynamic
62
+
52
63
在编译过程中,如果有变量被声明为字面量,例如` int i = 5; ` ,编译器就会对此变量进行优化处理,比如` i += 7 ` ,会直接在编译器中将` i ` 记录为12而非编译为记分板命令。而 ` dynamic ` 用于表示一个变量无论如何都会是编译时动态计算的,即使它是一个字面量。例如` dynamic int i = 5; ` ,` i ` 在编译时也会被当作一个动态变量,而不会被优化。
64
+
53
65
- const
66
+
54
67
` const ` 用于表示一个变量是一个常量,即它的值在编译时就已经确定了,且不会改变。例如` const int i = 5; ` ,` i ` 在编译时就会被当作一个常量。常量总是编译时静态的。常量的值必须在声明时就确定,不能在声明后再赋值。
68
+
55
69
- import
70
+
56
71
` import ` 用于表示一个变量是一个导入变量,即它的值是从其他地方导入的。例如` import int i; ` ,` i ` 在编译时就会被当作一个导入变量。一般来说,变量需要被赋值后才能使用,但是如果使用了` import ` 修饰符,那么变量就可以在声明后直接使用,而不需要赋值。
57
72
58
73
## 注释
74
+
59
75
``` cpp
60
76
// 单行注释
61
77
@@ -97,43 +113,57 @@ for(forinit;bool;forupdate){
97
113
break和continue语句是可用的。
98
114
99
115
## 命名空间
116
+
100
117
每个文件的命名空间可以被单独声明
118
+
101
119
``` cpp
102
120
namespace xxx ;
103
121
```
122
+
104
123
若文件没有单独声明命名空间,则为工程配置文件设置的命名空间。
105
124
106
125
## 函数
126
+
107
127
``` cpp
108
128
returnType identifier (type param...){
109
129
statement...
110
130
}
111
131
```
132
+
112
133
函数的命名空间由文件的命名空间决定。若文件没有单独声明命名空间,则为工程配置文件设置的命名空间。
134
+
113
135
:::warning{title=Note!}
114
136
mcfpp中的函数名只能包含字母、下划线及数字。
115
137
:::
138
+
116
139
return是可用的。
117
140
118
141
### 函数的注解
142
+
119
143
函数的注解是可选的,用于指定函数的一些特殊属性。
144
+
120
145
```cpp
121
146
@tag("example:qwq")
122
147
@tick()
123
148
void test(){
124
149
statement...
125
150
}
126
151
```
152
+
127
153
注解由一个` @ ` 符号开始,后面跟着一个标识符,然后是一对括号,括号中是注解的参数列表。注解中的参数只能为常量,不能为变量。
154
+
128
155
下面列出了mcfpp中的所有注解:
156
+
129
157
| 注解名| 参数| 描述|
130
158
| -----| ----| ----|
131
159
| tag| 一个命名空间id| 指定函数的标签|
132
160
| tick| 可选。一个非0整数,表示函数每隔多少tick执行一次。若不指定,则默认为每tick执行一次| 指定函数为tick函数|
133
161
| load| 无| 指定函数为load函数|
134
162
135
163
### static关键字
164
+
136
165
mcfpp的函数有一个特殊的形参形式用于返回,即static参数。static使得函数中对此变量的改变会影响到传入此函数的变量。例如
166
+
137
167
``` cpp
138
168
void test (static int a,int b){
139
169
a++;
@@ -146,17 +176,22 @@ void main(){
146
176
test(a,b);
147
177
}
148
178
```
179
+
149
180
最后结果a的值为1,b为0。
150
181
151
182
## 全局作用域 <Badge type="info">未来特性</Badge>
183
+
152
184
全局作用域是指在类和函数之外的域,可以在其中声明变量。全局作用域和命名空间有关。在全局作用域之内声明的变量可以在命名空间中的任意位置进行访问。全局作用域的声明语法是:
185
+
153
186
```cpp
154
187
global {
155
188
int i = 6;
156
189
}
157
190
158
191
```
192
+
159
193
一个命名空间下只能声明一次全局作用域。例如:
194
+
160
195
``` cpp
161
196
namespace test ;
162
197
@@ -171,33 +206,45 @@ void main(){
171
206
```
172
207
173
208
## 类
209
+
174
210
``` cpp
175
211
class ClassName {
176
212
classMember...
177
213
}
178
214
```
215
+
179
216
:::warning{title=Note!}
180
217
mcfpp中的类必须以大写字母开头。
181
218
:::
219
+
182
220
### 访问修饰符
221
+
183
222
- public 公开的
184
223
- protect 只有自己和子类能访问
185
224
- private (默认)私有的
186
225
187
226
### 类字段
227
+
188
228
`访问修饰符+普通的变量定义`
189
229
例如:`public int i;`
230
+
190
231
### 类函数
232
+
191
233
`访问修饰符+普通的函数定义`
192
234
例如:`public void qwq(){}`
193
235
194
236
**static是可用的**
195
237
196
238
### 构造函数
239
+
197
240
`访问修饰符+类名(参数){方法体}`
241
+
198
242
### 继承
243
+
199
244
`子类 : 父类/父接口`。允许继承多个类或接口。
245
+
200
246
使用`override`关键字,从而实现对父类或者父接口中方法的重写。
247
+
201
248
### super和this
202
249
203
250
调用父类构造方法:`super()`
@@ -213,6 +260,7 @@ mcfpp中的类必须以大写字母开头。
213
260
:::
214
261
215
262
下面是一个完整的类的例子
263
+
216
264
```cpp
217
265
class Student{
218
266
static int id;
@@ -233,12 +281,15 @@ class Student{
233
281
```
234
282
235
283
### 抽象类和抽象函数
284
+
236
285
在类前添加` abstract ` 关键字可以将这个类声明为抽象类。抽象类不能被实例化。
237
286
在函数前添加` abstract ` 关键字可以将这个函数声明为抽象函数。抽象函数不能含有函数体。
238
287
239
288
### 扩展方法
289
+
240
290
扩展方法使你能够向现有类型“添加”方法,而无需创建新的派生类型、重新编译或以其他方式修改原始类型。扩展方法在类的外部声明,但是可以像类的成员方法一样调用。
241
291
使用` 类名.方法名 ` 的形式来声明扩展方法,例如:
292
+
242
293
``` cpp
243
294
namespace test ;
244
295
@@ -270,19 +321,24 @@ static void Test.test2(){
270
321
print(Test.i);
271
322
}
272
323
```
324
+
273
325
## 接口
326
+
274
327
```cpp
275
328
interface InterfaceName{
276
329
interfaceMember...
277
330
}
278
331
```
332
+
279
333
你可以在接口中声明抽象函数。接口可以继承于其他接口。
280
334
281
335
## 结构体
336
+
282
337
结构体是一种完全由记分板构成的数据结构,因此结构体中只能有记分板变量,即` int ` 类型的变量作为成员。
283
338
在声明字段的时候,可以将字段类型` int ` 省略不写。
284
339
除此之外结构体和类几乎完全一致。
285
340
下面是一个结构体的例子:
341
+
286
342
``` cpp
287
343
struct FloatStruct {
288
344
public static int index;
@@ -299,8 +355,11 @@ struct FloatStruct{
299
355
}
300
356
}
301
357
```
358
+
302
359
:::warning{title=Note!}
360
+
303
361
#### 类和结构体的区别
362
+
304
363
虽然语法和功能基本一致,但是类和结构体在实现原理上有着本质的区别。
305
364
306
365
类是一个对象,而结构体是一个数据结构。
@@ -312,17 +371,24 @@ struct FloatStruct{
312
371
313
372
314
373
## MNI
374
+
315
375
MNI类似于Java中的JNI,是一种编程框架,使得编译器在程序编译的过程中可以调用由**Java**代码编写的本地程序,从而实现更灵活的编写。MNI只存在于编译过程中,而不能存在于运行过程中。
316
376
317
377
### native函数
378
+
318
379
native可以被声明在类或者函数中,用于在**编译**阶段调用运行指定的一个java函数。
380
+
319
381
它的声明是这样的:
382
+
320
383
```cpp
321
384
native test(params...) -> packagename.classname.funcname;
322
385
```
386
+
323
387
前面是一个普通的函数声明(但是不包括返回类型,也就是说native函数没有返回类型),箭头所指的则是java中的一个方法的完整路径,包括包,类和方法名。
388
+
324
389
相应的java函数的声明有一个要求,即函数的参数必须为` (Var[] xxx, ClassBase cls) ` 。` Var[] xxx ` 是调用这个函数时传入的参数的信息,` ClassBase cls ` 是这个函数所在的类的对象。如果这个函数不是一个类的成员,则` cls ` 参数将会是` null `
325
- 这是一个例子,也是是mcfpp基本库的一部分,即print函数的实现:
390
+
391
+ 这是一个例子,也是mcfpp基本库的一部分,即print函数的实现:
326
392
327
393
** System.java**
328
394
``` js
0 commit comments