forked from Mwexim/skript-parser
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathStructFunction.java
More file actions
118 lines (107 loc) · 4.94 KB
/
StructFunction.java
File metadata and controls
118 lines (107 loc) · 4.94 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
package io.github.syst3ms.skriptparser.structures.functions;
import io.github.syst3ms.skriptparser.Parser;
import io.github.syst3ms.skriptparser.lang.Expression;
import io.github.syst3ms.skriptparser.lang.Literal;
import io.github.syst3ms.skriptparser.lang.Structure;
import io.github.syst3ms.skriptparser.lang.Trigger;
import io.github.syst3ms.skriptparser.lang.TriggerContext;
import io.github.syst3ms.skriptparser.log.ErrorType;
import io.github.syst3ms.skriptparser.log.SkriptLogger;
import io.github.syst3ms.skriptparser.parsing.ParseContext;
import io.github.syst3ms.skriptparser.types.Type;
import io.github.syst3ms.skriptparser.types.TypeManager;
public class StructFunction extends Structure {
static {
Parser.getMainRegistration()
.newStructure(StructFunction.class, "*[:local[ ]] func[tion] <" + Functions.FUNCTION_NAME_REGEX + ">" +
"\\([params:%*functionparameters%]\\)[return: (\\:\\:|returns|-\\>) <.+>]")
.setHandledContexts(FunctionContext.class)
.name("Function")
.description("Creates a function that can be called from other scripts.",
"`local` indicates a function that can only be called from the same script.")
.since("1.0.0")
.examples("function getName(p: player) :: string:",
"\treturn name of {_p}",
"",
"function getLocation(e: entity) returns location:",
"\treturn location of {_e}",
"",
"function getWorld(e: entity) -> world:",
"\treturn world of {_e}",
"",
"function spawn(p: players):",
"\tteleport {_p::*} to {spawn}",
"",
"function broadcast(m: string, p: players):",
"\tsend {_m} to {_p::*}")
.register();
}
private Literal<FunctionParameter<?>> params;
private boolean returnSingle = true;
private String rawReturnType;
private String functionName;
private boolean local;
private ScriptFunction<?> function; // to be registered in the register method
@Override
public boolean check(TriggerContext ctx) {
return ctx instanceof FunctionContext;
}
@SuppressWarnings("unchecked")
@Override
public boolean init(Expression<?>[] expressions, int matchedPattern, ParseContext parseContext) {
local = parseContext.hasMark("local");
functionName = parseContext.getMatches().get(0).group();
SkriptLogger logger = parseContext.getLogger();
if (!Functions.isValidFunctionName(functionName)) {
logger.error("'" + functionName + "' is not a valid function name.", ErrorType.SEMANTIC_ERROR);
return false;
}
FunctionParameter<?>[] parameters = null;
if (parseContext.getMarks().contains("params")) {
params = (Literal<FunctionParameter<?>>) expressions[0];
parameters = params.getValues();
for (FunctionParameter<?> parameter : parameters) {
for (FunctionParameter<?> p : parameters) {
if (p == parameter) continue;
if (parameter.getName().equals(p.getName())) {
logger.error("Functions parameters cannot have the same name.", ErrorType.SEMANTIC_ERROR);
return false;
}
}
}
}
Class<?> returnType = null;
if (parseContext.getMarks().contains("return")) {
rawReturnType = parseContext.getMatches().get(1).group();
Type<?> type = TypeManager.parseType(rawReturnType);
if (type == null) {
logger.error("The type provided was unable to be parsed.", ErrorType.SEMANTIC_ERROR);
return false;
}
returnType = type.getTypeClass();
if (returnType == FunctionParameter.class) {
logger.error("This type should not be used as a function's return type.", ErrorType.SEMANTIC_ERROR);
return false;
}
if (type.isPlural(rawReturnType)) returnSingle = false;
}
String scriptName = parseContext.getLogger().getFileName().replace(".sk", "");
function = new ScriptFunction<>(scriptName, local, functionName, parameters, returnType, returnSingle);
if (!Functions.isValidFunction(function, parseContext.getLogger())) {
return false;
}
Functions.preRegisterFunction(function);
return true;
}
@Override
public String toString(TriggerContext ctx, boolean debug) {
return (local ? "local " : "") + "function " + functionName + "(" + params.toString(ctx, debug) + ")" +
(rawReturnType == null ? "" : " :: " + rawReturnType);
}
public String getStringName() {
return functionName;
}
public void register(Trigger trigger) {
Functions.registerFunction(function, trigger);
}
}