firefly-compiler 0.6.21 → 0.6.24

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "editor.suggest.showWords": false,
3
- "firefly.trace.server": "messages",
3
+ "firefly.trace.server": "verbose",
4
4
  "editor.trimAutoWhitespace": false
5
5
  }
@@ -819,12 +819,28 @@ extend self: Inference {
819
819
  self.unification.unify(term.at, selfParameter.valueType, recordType)
820
820
  let arguments = self.inferArguments(term.at, name, environment, signature.parameters.dropFirst(), e.arguments)
821
821
  self.unification.affect(term.at, signature.effect, environment.effect)
822
- e.ECall(
822
+ let result = e.ECall(
823
823
  target = StaticCall(name, instanceCall = False, tailCall = tailCall)
824
824
  typeArguments = instantiation.map {_.second}
825
825
  arguments = [selfArgument, ...arguments]
826
826
  effect = signature.effect
827
827
  )
828
+ if(self.lspHook.sql) {
829
+ if(name == "ff:postgresql/Pg.PgConnection_statement") {
830
+ self.lspHook.sqlStrings.push(result)
831
+ } elseIf {name == "ff:postgresql/Pg.PgStatement_map"} {
832
+ self.lspHook.sqlStrings.push(result)
833
+ } elseIf {name == "ff:postgresql/Pg.PgStatement_each"} {
834
+ self.lspHook.sqlStrings.push(result)
835
+ } elseIf {name == "ff:postgresql/Pg.PgStatement_any"} {
836
+ self.lspHook.sqlStrings.push(result)
837
+ } elseIf {name == "ff:postgresql/Pg.PgStatement_all"} {
838
+ self.lspHook.sqlStrings.push(result)
839
+ } elseIf {name == "ff:postgresql/Pg.PgStatement_run"} {
840
+ self.lspHook.sqlStrings.push(result)
841
+ }
842
+ }
843
+ result
828
844
  | _ => fail(term.at, "Call expected")
829
845
  }
830
846
  }
@@ -8,19 +8,29 @@ class LspHook(
8
8
  insertIdentifier: Bool
9
9
  trackSymbols: Bool
10
10
  arrayOfResults: Array[ResultHook]
11
+ sql: Bool
12
+ sqlStrings: Array[Term]
11
13
  )
12
14
 
13
- disabled(): LspHook {
14
- new(None, None, False, False)
15
+ disabled(sql: Bool = False): LspHook {
16
+ new(None, None, False, False, sql)
15
17
  }
16
18
 
17
- new(at: Option[Location], definedAt: Option[Location], insertIdentifier: Bool, trackSymbols: Bool): LspHook {
19
+ new(
20
+ at: Option[Location]
21
+ definedAt: Option[Location]
22
+ insertIdentifier: Bool
23
+ trackSymbols: Bool
24
+ sql: Bool = False
25
+ ): LspHook {
18
26
  LspHook( // Default dummy values instead of Option[Location] to speed up location hit check
19
27
  at = at.else {Location("^lsp", -7, -7)}
20
28
  definedAt = definedAt.else {Location("^lsp", -7, -7)}
21
29
  insertIdentifier = insertIdentifier
22
30
  trackSymbols = trackSymbols
23
- arrayOfResults = [].toArray()
31
+ arrayOfResults = Array.new()
32
+ sql = sql
33
+ sqlStrings = Array.new()
24
34
  )
25
35
  }
26
36
 
@@ -200,4 +210,4 @@ showHook(hook: ResultHook): String {
200
210
  | ResolveSymbolHook(symbol, annotation, _) => "ResolveSymbolHook(...)"
201
211
  | ResolveTypeHook(types, typeGenerics, symbol, explicitType) => "ResolveTypeHook(...)"
202
212
  | ResolveVariantFieldHook(symbol, type, commonField) => "ResolveVariantFieldHook(...)"
203
- }
213
+ }
package/core/Ordering.ff CHANGED
@@ -91,7 +91,7 @@ instance List[T: Order]: Order {
91
91
  ordering = compare(x.grab(i), y.grab(i))
92
92
  i += 1
93
93
  }
94
- if(ordering != OrderingSame) {
94
+ if(ordering == OrderingSame) {
95
95
  fromInt(x.size() - y.size())
96
96
  } else {
97
97
  ordering
@@ -0,0 +1,47 @@
1
+ nodeMain(system: NodeSystem) {
2
+ let secretKey = system.arguments().grab(0)
3
+ let json = Json->(
4
+ model = "moonshotai/Kimi-K2.6"
5
+ messages = [
6
+ Json->(role = "user", content = "Can you summerize firefly-lang.org for me.")
7
+ ]
8
+ tools = [
9
+ Json->(type = "function", function = Json->(
10
+ name = "web_search"
11
+ description = "Search the web for up-to-date information, images, or data based on a query."
12
+ parameters = Json->(
13
+ type = "object"
14
+ properties = Json->(
15
+ query = Json->(
16
+ type = "string"
17
+ description = "The search query to look up on the web."
18
+ )
19
+ )
20
+ required = ["query"]
21
+ )
22
+ ))
23
+ Json->(type = "function", function = Json->(
24
+ name = "web_fetch"
25
+ description = "Fetch the contents of a URL using a GET request."
26
+ parameters = Json->(
27
+ type = "object"
28
+ properties = Json->(
29
+ url = Json->(
30
+ type = "string"
31
+ description = "The URL to fetch."
32
+ )
33
+ )
34
+ required = ["url"]
35
+ )
36
+ ))
37
+ ]
38
+ )
39
+ // To give a tool result: {"role": "tool", "content": "... e.g. encoded JSON", "tool_call_id": "call_123"}
40
+ system.httpClient().post("https://api.inceptron.io/v1/chat/completions", [
41
+ Pair("Content-Type", "application/json")
42
+ Pair("Authorization", "Bearer " + secretKey)
43
+ ], json.write().toBuffer()) {response =>
44
+ Log.debug("Response ok? " + Show.show(response.ok()))
45
+ Log.debug(response.readJson().write(Some(" ")))
46
+ }
47
+ }
@@ -0,0 +1,44 @@
1
+ nodeMain(system: NodeSystem) {
2
+
3
+ let x: Float = 123.0
4
+ let s: String = "Hi"
5
+ let p = s + x
6
+ let r1: Int = 123.8.round().toInt()
7
+ Log.show(p)
8
+
9
+ let player = Human("RawFood23", None)
10
+ let bot = Bot(42)
11
+
12
+ let players: List[Player] = [
13
+ Human("RawFood23", None)
14
+ Human("Nokoline123", Some(system.date()))
15
+ bot
16
+
17
+ ]
18
+
19
+ players.each {
20
+ | Human(name, None) =>
21
+ Log.trace(name + " is in lobby")
22
+ | Human(name, Some(joined)) =>
23
+ Log.trace(name + " joined at " + Show.show(joined))
24
+ | Bot(n) =>
25
+ Log.trace("Bot nr. " + n)
26
+ }
27
+
28
+ let player2 = (name = "Jogn", age = 11)
29
+
30
+ }
31
+
32
+ addPlayer(player: Player) {
33
+
34
+ }
35
+
36
+ data Player {
37
+ Human(
38
+ name: String
39
+ joined: Option[Date]
40
+ )
41
+ Bot(
42
+ number: Int
43
+ )
44
+ }
@@ -0,0 +1,7 @@
1
+ nodeMain(system: NodeSystem) {
2
+
3
+ let result = Ordering.compare([1], [2])
4
+ Log.debug(Show.show(result.toInt()))
5
+
6
+
7
+ }
@@ -0,0 +1,4 @@
1
+ nodeMain(system: NodeSystem) {
2
+ let result = Ordering.compare([1], [2])
3
+ Log.trace(Show.show(result.toInt()))
4
+ }
@@ -0,0 +1,18 @@
1
+ dependency ff:postgresql:0.0.0
2
+
3
+ import Pg from ff:postgresql
4
+
5
+
6
+ testSql(connection: PgConnection): List[String] {
7
+ connection.statement("""
8
+ -- Comment
9
+ select *, benefit, g.deleted, 'Fooo', 123
10
+ from guide."GuideHistory" g
11
+ join guide."GuideDepartment" GD on g.id = GD.guideid
12
+ where g.benefit is not null and $name = '0x42' and true
13
+ """)
14
+ .withInt("name", 34)
15
+ .map {row =>
16
+ row.getString("name").grab()
17
+ }
18
+ }
@@ -1 +1,2 @@
1
1
  dependency ff:compiler:0.0.0
2
+ dependency ff:postgresql:0.0.0
@@ -3,6 +3,9 @@ import Unification from ff:compiler
3
3
  import Environment from ff:compiler
4
4
  import Syntax from ff:compiler
5
5
  import Handler
6
+ import Sql
7
+ import SqlSuggestion
8
+ import SqlStatement
6
9
 
7
10
  data CompletionInfo(
8
11
  label: String
@@ -15,6 +18,7 @@ data CompletionInfo(
15
18
  expectedType: Option[Type]
16
19
  secondarySort: Int = 5
17
20
  insertion: Option[Pair[Int, String]] = None
21
+ sql: Bool = False
18
22
  )
19
23
 
20
24
  data ImportSymbolsInfo(
@@ -35,7 +39,10 @@ handleCompletion(
35
39
  toplevel: Bool
36
40
  followedByOpenBracket: Bool
37
41
  importSymbols: ImportSymbolsInfo
42
+ sqlStatement: Option[Pair[Location, SqlStatement]]
43
+ sqlData: SqlData
38
44
  ): Json {
45
+ sqlStatement.map {| Pair(l, s) => completionsToJson(sqlCompletion(l, s, sqlData))}.else:
39
46
  let topLevelCompletions = if(!toplevel) {[]} else {toplevelCompletion(lspHook)}
40
47
  let patternCompletions = lspHook.results().collectFirst {
41
48
  | InferPatternHook h =>
@@ -195,10 +202,14 @@ completionsToJson(completions: List[CompletionInfo]): Json {
195
202
  let isDefinition = ["let ", "mutable ", "function "].any {i.snippet.startsWith(_)}
196
203
  let isParameter = i.snippet.endsWith(" = ")
197
204
  let isImport = i.documentation == "// Imports this module"
198
- let sortText = if(isParameter || isDefinition || isImport) {0} else {9 - (
199
- isVariable.toInt() + isUnqualified.toInt() +
200
- isAlpha.toInt() + isLower.toInt() + isMember.toInt()
201
- )} + if(isMember) {"1"} else {"0"} + i.secondarySort + i.label.lower()
205
+ let sortText = if(i.sql && i.extra == "") {
206
+ i.secondarySort + i.label.lower()
207
+ } else {
208
+ if(isParameter || isDefinition || isImport) {0} else {9 - (
209
+ isVariable.toInt() + isUnqualified.toInt() +
210
+ isAlpha.toInt() + isLower.toInt() + isMember.toInt()
211
+ )} + if(isMember) {"1"} else {"0"} + i.secondarySort + i.label.lower()
212
+ }
202
213
  let preselect = !isDefinition && Pair(i.type, i.expectedType).{
203
214
  | Pair(TConstructor(_, n1, _), Some(TConstructor(_, n2, _))) => n1 == n2
204
215
  | _ => False
@@ -206,6 +217,16 @@ completionsToJson(completions: List[CompletionInfo]): Json {
206
217
  Json.object()
207
218
  // Namespace or Property or Constructor or EnumMember or Constructor or Method/Function or Field/Variable
208
219
  .with("kind"
220
+ if(i.sql) {
221
+ if(i.secondarySort == 1) {15} else:
222
+ if(i.secondarySort == 2) {23} else:
223
+ if(i.secondarySort == 3) {7} else:
224
+ if(i.secondarySort == 4) {5} else:
225
+ if(i.secondarySort == 5) {6} else:
226
+ if(i.secondarySort == 8) {3} else:
227
+ if(i.secondarySort == 9) {15} else:
228
+ 9
229
+ } else:
209
230
  if(isImport) {2} else:
210
231
  if(shownType == "") {3} else:
211
232
  if(isParameter) {10} else:
@@ -218,14 +239,18 @@ completionsToJson(completions: List[CompletionInfo]): Json {
218
239
  .with("preselect", preselect)
219
240
  .with("label", i.label)
220
241
  .with("labelDetails", Json.object()
221
- .with("detail", i.extra + if(shownType == "") {""} else {": " + shownType})
242
+ .with("detail", if(i.sql) {i.extra} else {
243
+ i.extra + if(shownType == "") {""} else {": " + shownType}
244
+ })
222
245
  .with("description", i.more)
223
246
  )
224
247
  .with("insertText", i.snippet)
225
248
  .with("insertTextFormat", 2 /* Snippet */)
226
249
  .with("documentation", Json.object()
227
250
  .with("kind", "markdown")
228
- .with("value", "```\n" + i.documentation + "\n```")
251
+ .with("value",
252
+ if(i.sql) {"```sql\n"} else {"```\n"} + i.documentation + "\n```"
253
+ )
229
254
  )
230
255
  .with("additionalTextEdits", i.insertion.toList().map {| Pair(line, text) => Json.object()
231
256
  .with("range", Json->(
@@ -237,6 +262,87 @@ completionsToJson(completions: List[CompletionInfo]): Json {
237
262
  })
238
263
  }
239
264
 
265
+ sqlCompletion(at: Location, sqlStatement: SqlStatement, data: SqlData): List[CompletionInfo] {
266
+ let tokens = Sql.tokenize(sqlStatement.string)
267
+ let line = 1 + at.line - sqlStatement.at.line
268
+ let column = if(at.line == sqlStatement.at.line) {1 + at.column - sqlStatement.at.column} else {at.column}
269
+ let suggestions = SqlSuggestion.suggest(data, tokens, line, column)
270
+ function fixQuotes(snippet: String): String {
271
+ if(suggestions.second) {snippet.replace("\"", "")} else {snippet}
272
+ }
273
+ suggestions.first.map {
274
+ | SqlSuggestionFunction(l, signature, documentation)@suggestion =>
275
+ CompletionInfo(
276
+ label = l
277
+ extra = signature
278
+ more = ""
279
+ snippet = fixQuotes(Sql.quote(l) + "($0)")
280
+ member = False
281
+ type = TConstructor(Location("", 0, 0), "", [])
282
+ documentation = documentation
283
+ expectedType = None
284
+ sql = True
285
+ secondarySort = suggestion.secondarySort()
286
+ )
287
+ | SqlSuggestionJoin(l, schema, snippet)@suggestion =>
288
+ CompletionInfo(
289
+ label = l
290
+ extra = ""
291
+ more = schema
292
+ snippet = fixQuotes(snippet)
293
+ member = False
294
+ type = TConstructor(Location("", 0, 0), "", [])
295
+ documentation = snippet
296
+ expectedType = None
297
+ sql = True
298
+ secondarySort = suggestion.secondarySort()
299
+ )
300
+ | SqlSuggestionRegular(l, display, documentation)@suggestion =>
301
+ CompletionInfo(
302
+ label = l
303
+ extra = ""
304
+ more = display
305
+ snippet = fixQuotes(Sql.quote(l))
306
+ member = False
307
+ type = TConstructor(Location("", 0, 0), "", [])
308
+ documentation = documentation
309
+ expectedType = None
310
+ sql = True
311
+ secondarySort = suggestion.secondarySort()
312
+ )
313
+ | SqlSuggestionColumnNames(required, columns)@suggestion =>
314
+ let comment =
315
+ if(required) {"-- required columns\n"} elseIf {columns.size() > 1} {"-- all columns\n"} else {""}
316
+ CompletionInfo(
317
+ label = columns.map {_.first}.join(", ")
318
+ extra = ""
319
+ more = ""
320
+ snippet = fixQuotes(columns.map {Sql.quote(_.first)}.join(", "))
321
+ member = False
322
+ type = TConstructor(Location("", 0, 0), "", [])
323
+ documentation = comment + columns.map {_.second}.join("\n")
324
+ expectedType = None
325
+ sql = True
326
+ secondarySort = suggestion.secondarySort()
327
+ )
328
+ | SqlSuggestionColumnSetters(columns)@suggestion =>
329
+ CompletionInfo(
330
+ label = columns.map {_.first + " = "}.join(", ")
331
+ extra = ""
332
+ more = ""
333
+ snippet = fixQuotes(columns.pairs().map {| Pair(i, c) =>
334
+ Sql.quote(c.first) + " = " + if(i == 0) {"$0"} else {""}
335
+ }.join(",\n"))
336
+ member = False
337
+ type = TConstructor(Location("", 0, 0), "", [])
338
+ documentation = columns.map {_.second}.join("\n")
339
+ expectedType = None
340
+ sql = True
341
+ secondarySort = suggestion.secondarySort()
342
+ )
343
+ }
344
+ }
345
+
240
346
  importCompletion(moduleKeys: List[ModuleKey]): List[CompletionInfo] {
241
347
  moduleKeys.map {moduleKey =>
242
348
  let label = moduleKey.folders.map {_ + "."}.join() + moduleKey.name