firefly-compiler 0.5.65 → 0.5.66

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.
@@ -172,7 +172,12 @@ extend self: Parser {
172
172
  } elseIf {self.current().is(LKeyword) && self.current().rawIs4("data", "class", "capability", "newtype")} {
173
173
  types.push(self.parseTypeDefinition())
174
174
  } elseIf {self.current().is(LKeyword) && self.current().rawIs("import")} {
175
- imports.push(self.parseImportDefinition(self.moduleKey.packagePair))
175
+ if(self.lspHook.isEnabled() && self.ahead().is(LLower) && !self.aheadAhead().is(LDot)) {
176
+ self.skip(LKeyword)
177
+ self.skip(LLower)
178
+ } else {
179
+ imports.push(self.parseImportDefinition(self.moduleKey.packagePair))
180
+ }
176
181
  } elseIf {self.current().is(LKeyword) && self.current().rawIs("include")} {
177
182
  throw(CompileError(self.current().at()
178
183
  "Includes must be at the top of the file or below 'package'"
@@ -14,9 +14,28 @@ data CompletionInfo(
14
14
  documentation: String
15
15
  expectedType: Option[Type]
16
16
  secondarySort: Int = 5
17
+ insertion: Option[Pair[Int, String]] = None
17
18
  )
18
19
 
19
- handleCompletion(lspHook: LspHook, toplevel: Bool, followedByOpenBracket: Bool): Json {
20
+ data ImportSymbolsInfo(
21
+ import: Bool
22
+ importSymbols: List[ImportSymbolInfo]
23
+ importLine: Int
24
+ )
25
+
26
+ data ImportSymbolInfo(
27
+ moduleKey: ModuleKey
28
+ typeNames: List[String]
29
+ variantNames: List[String]
30
+ traitNames: List[String]
31
+ )
32
+
33
+ handleCompletion(
34
+ lspHook: LspHook
35
+ toplevel: Bool
36
+ followedByOpenBracket: Bool
37
+ importSymbols: ImportSymbolsInfo
38
+ ): Json {
20
39
  let topLevelCompletions = if(!toplevel) {[]} else {toplevelCompletion(lspHook)}
21
40
  let patternCompletions = lspHook.results().collectFirst {
22
41
  | InferPatternHook h =>
@@ -59,10 +78,11 @@ handleCompletion(lspHook: LspHook, toplevel: Bool, followedByOpenBracket: Bool):
59
78
  } {
60
79
  scheme.signature.returnType | TConstructor(_, selfTypeName, _)
61
80
  } =>
62
- let otherCompletions = completion(h.unification, h.environment, "", None, expected)
81
+ let otherCompletions =
82
+ completion(h.unification, h.environment, "", None, expected, importSymbols)
63
83
  let selfCompletions = h.environment.symbols.get(selfName).toList().flatMap {scheme =>
64
84
  let prefix = selfTypeName + "_"
65
- completion(h.unification, h.environment, prefix, None, expected).filter {
85
+ completion(h.unification, h.environment, prefix, None, expected, importSymbols).filter {
66
86
  _.label.first().any {_.isAsciiLower()}
67
87
  }.map {c =>
68
88
  c.CompletionInfo(label = selfName + "." + c.label, snippet = selfName + "." + c.snippet)
@@ -70,7 +90,7 @@ handleCompletion(lspHook: LspHook, toplevel: Bool, followedByOpenBracket: Bool):
70
90
  }
71
91
  [...otherCompletions, ...selfCompletions]
72
92
  | _ =>
73
- completion(h.unification, h.environment, typePrefix, qualifiedByAlias, expected)
93
+ completion(h.unification, h.environment, typePrefix, qualifiedByAlias, expected, importSymbols)
74
94
  }
75
95
  | InferRecordFieldHook h {h.unification.substitute(h.recordType) | TConstructor(_, n, ts)} =>
76
96
  let fieldNames = n.split('$').dropFirst(1)
@@ -78,7 +98,7 @@ handleCompletion(lspHook: LspHook, toplevel: Bool, followedByOpenBracket: Bool):
78
98
  let t2 = h.unification.substitute(t)
79
99
  CompletionInfo(name, "", "", name, True, t2, "(...)." + name + ": " + t2.show([]), Some(h.expected))
80
100
  }
81
- [...fieldCompletions, ...completion(h.unification, h.environment, n, None, h.expected)]
101
+ [...fieldCompletions, ...completion(h.unification, h.environment, n, None, h.expected, importSymbols)]
82
102
  | InferArgumentHook h {
83
103
  ![ // Avoids named argument suggestions for operators that become trait method calls, such as ==
84
104
  "ff:core/Equal.equals", "ff:core/Equal.notEquals"
@@ -157,7 +177,9 @@ handleCompletion(lspHook: LspHook, toplevel: Bool, followedByOpenBracket: Bool):
157
177
  } else {c}
158
178
  }
159
179
  }
160
- completionsToJson([...fixedCompletions, ...fixedTypeCompletions, ...topLevelCompletions])
180
+ let importCompletions =
181
+ importCompletion(importSymbols.importSymbols.filter {_ => importSymbols.import}.map {_.moduleKey})
182
+ completionsToJson([...fixedCompletions, ...fixedTypeCompletions, ...topLevelCompletions, ...importCompletions])
161
183
  }
162
184
 
163
185
  completionsToJson(completions: List[CompletionInfo]): Json {
@@ -172,7 +194,8 @@ completionsToJson(completions: List[CompletionInfo]): Json {
172
194
  let isVariable = isLower && !i.extra.contains("(") && !i.extra.contains("{")
173
195
  let isDefinition = ["let ", "mutable ", "function "].any {i.snippet.startsWith(_)}
174
196
  let isParameter = i.snippet.endsWith(" = ")
175
- let sortText = if(isParameter || isDefinition) {0} else {9 - (
197
+ let isImport = i.documentation == "// Imports this module"
198
+ let sortText = if(isParameter || isDefinition || isImport) {0} else {9 - (
176
199
  isVariable.toInt() + isUnqualified.toInt() +
177
200
  isAlpha.toInt() + isLower.toInt() + isMember.toInt()
178
201
  )} + if(isMember) {"1"} else {"0"} + i.secondarySort + i.label.lower()
@@ -183,6 +206,7 @@ completionsToJson(completions: List[CompletionInfo]): Json {
183
206
  Json.object()
184
207
  // Namespace or Property or Constructor or EnumMember or Constructor or Method/Function or Field/Variable
185
208
  .with("kind"
209
+ if(isImport) {2} else:
186
210
  if(shownType == "") {3} else:
187
211
  if(isParameter) {10} else:
188
212
  if(i.type.{| TConstructor(_, "type", _) => True | _ => False}) {9} else:
@@ -203,9 +227,38 @@ completionsToJson(completions: List[CompletionInfo]): Json {
203
227
  .with("kind", "markdown")
204
228
  .with("value", "```\n" + i.documentation + "\n```")
205
229
  )
230
+ .with("additionalTextEdits", i.insertion.toList().map {| Pair(line, text) => Json.object()
231
+ .with("range", Json->(
232
+ start = Json->(line = line - 1, character = 0)
233
+ end = Json->(line = line - 1, character = 0)
234
+ ))
235
+ .with("newText", text)
236
+ })
206
237
  })
207
238
  }
208
239
 
240
+ importCompletion(moduleKeys: List[ModuleKey]): List[CompletionInfo] {
241
+ moduleKeys.map {moduleKey =>
242
+ let label = moduleKey.folders.map {_ + "."}.join() + moduleKey.name
243
+ let extra = if(moduleKey.packagePair.name == "script" && moduleKey.packagePair.group == "script") {
244
+ ""
245
+ } else {
246
+ " from " + moduleKey.packagePair.groupName(":")
247
+ }
248
+ CompletionInfo(
249
+ label = label
250
+ extra = extra
251
+ more = ""
252
+ snippet = label + extra
253
+ member = False
254
+ type = TConstructor(Location("", 0, 0), "", [])
255
+ documentation = "// Imports this module",
256
+ expectedType = None
257
+ secondarySort = if(extra == "") {1} else {2}
258
+ )
259
+ }
260
+ }
261
+
209
262
  typeCompletion(types: Map[String, String], typeGenerics: Map[String, List[String]]): List[CompletionInfo] {
210
263
  let completions = types.toList().filter {| Pair(n, full) =>
211
264
  n.all {_.isAsciiLetterOrDigit()}
@@ -226,6 +279,7 @@ completion(
226
279
  prefix: String
227
280
  qualifiedByAlias: Option[String]
228
281
  expected: Type
282
+ importSymbols: ImportSymbolsInfo
229
283
  ): List[CompletionInfo] {
230
284
 
231
285
  let member = prefix.contains("_")
@@ -299,6 +353,35 @@ completion(
299
353
  members.push(makeCompletion(unification, expected, prefix, memberName, memberScheme, False, member))
300
354
  }
301
355
  }
356
+
357
+ if(prefix == "") {
358
+ importSymbols.importSymbols.each {| info =>
359
+ [info.moduleKey.name, ...info.variantNames].distinct().each: name =>
360
+ let moduleName = info.moduleKey.folders.map {_ + "."}.join() + info.moduleKey.name
361
+ let fromName = if(
362
+ info.moduleKey.packagePair.name == "script" && info.moduleKey.packagePair.group == "script"
363
+ ) {
364
+ ""
365
+ } else {
366
+ info.moduleKey.packagePair.groupName(":")
367
+ }
368
+ let importName = if(fromName == "") {moduleName} else {moduleName + " from " + fromName}
369
+ // TODO: Add edit that inserts the import
370
+ members.push(CompletionInfo(
371
+ label = name
372
+ extra = ""
373
+ more = if(fromName == "") {moduleName} else {fromName + "/" + moduleName}
374
+ snippet = name
375
+ member = False
376
+ type = TConstructor(Location("", 0, 0), "", [])
377
+ documentation = "// Will import the following module:\nimport " + importName
378
+ expectedType = None
379
+ secondarySort = 9
380
+ insertion = Some(Pair(importSymbols.importLine, "import " + importName + "\n"))
381
+ ))
382
+ }
383
+ }
384
+
302
385
  members.toList()
303
386
  }
304
387
 
package/lsp/Handler.ff CHANGED
@@ -1,5 +1,6 @@
1
1
  import JsEmitter from ff:compiler
2
2
  import Builder from ff:compiler
3
+ import Dependencies from ff:compiler
3
4
  import Syntax from ff:compiler
4
5
  import Tokenizer from ff:compiler
5
6
  import Parser from ff:compiler
@@ -21,6 +22,7 @@ capability Handler(
21
22
  mutable cancelledRequests: Set[MessageId]
22
23
  mutable responseCache: Map[TokenRequestCacheKey, ResultOrError]
23
24
  mutable fileSymbolsCache: Map[String, List[DocumentSymbol]]
25
+ mutable importSymbolsCache: Pair[String, List[ImportSymbolInfo]]
24
26
  moduleCache: ModuleCache
25
27
  dependencyLock: DependencyLock
26
28
  )
@@ -93,11 +95,15 @@ extend self: Handler {
93
95
 
94
96
  handleRequest(system: NodeSystem, method: String, parameters: Map[String, Json], version: Int): ResultOrError {
95
97
  method.{
96
- | "initialize" => self.handleInitialize(system, parameters)
98
+ | "initialize" =>
99
+ self.handleInitialize(system, parameters)
97
100
  //| "textDocument/diagnostic" => self.handleDiagnostic(system, parameters)
98
- | "textDocument/documentSymbol" => self.handleDocumentSymbol(system, parameters)
99
- | "textDocument/completion" => self.handleCompletion(system, parameters, version)
100
- | "textDocument/signatureHelp" => self.handleSignatureHelp(system, parameters, version)
101
+ | "textDocument/documentSymbol" =>
102
+ self.handleDocumentSymbol(system, parameters)
103
+ | "textDocument/completion" =>
104
+ self.handleCompletion(system, parameters, version)
105
+ | "textDocument/signatureHelp" =>
106
+ self.handleSignatureHelp(system, parameters, version)
101
107
  | "textDocument/hover" =>
102
108
  self.handleTokenRequestWithCache(system, method, parameters) {key =>
103
109
  self.handleHover(system, key.targetAt, goToDefinition = False, version)
@@ -110,7 +116,8 @@ extend self: Handler {
110
116
  self.handleTokenRequestWithCache(system, method, parameters) {key =>
111
117
  self.handleReferences(system, key.targetAt, key.includeDeclaration, local = False, version)
112
118
  }
113
- | "textDocument/rename" => self.handleRename(system, parameters, version)
119
+ | "textDocument/rename" =>
120
+ self.handleRename(system, parameters, version)
114
121
  | "textDocument/documentHighlight" =>
115
122
  self.handleTokenRequestWithCache(system, method, parameters) {key =>
116
123
  self.handleReferences(system, key.targetAt, includeDeclaration = True, local = True, version)
@@ -119,8 +126,10 @@ extend self: Handler {
119
126
  self.printTime(system.mainTask(), "handleWorkspaceSymbol") {
120
127
  self.handleWorkspaceSymbol(system, parameters)
121
128
  }
122
- | "shutdown" => Result(Json.null().write())
123
- | _ => self.handleUnsupported()
129
+ | "shutdown" =>
130
+ Result(Json.null().write())
131
+ | _ =>
132
+ self.handleUnsupported()
124
133
  }
125
134
  }
126
135
 
@@ -231,6 +240,7 @@ extend self: Handler {
231
240
  }*/
232
241
 
233
242
  handleFocusDiagnostic(system: NodeSystem, parameters: Map[String, Json], version: Int): Json {
243
+ self.importSymbolsCache = Pair("", [])
234
244
  let js = system.js()
235
245
  let uri = parameters.grab("textDocument").field("uri").grabString()
236
246
  let path = system.pathFromUrl(uri)
@@ -384,6 +394,7 @@ extend self: Handler {
384
394
  handleCompletion(system: NodeSystem, parameters: Map[String, Json], version: Int): ResultOrError {
385
395
  let location = self.findLocationFromParameters(system, parameters)
386
396
  let token = self.findToken(system, location, insertToken = True)
397
+ let toplevelToken = self.findToken(system, location.Location(column = 1), insertToken = False)
387
398
  let completionAt = Location(
388
399
  file = location.file
389
400
  line = token.startLine
@@ -395,7 +406,17 @@ extend self: Handler {
395
406
  errors.each {| CompileError(at, message) =>
396
407
  Log.trace("handleCompletion check error: " + message)
397
408
  }
398
- let o = CompletionHandler.handleCompletion(lspHook, completionAt.column == 1, token.followedByLeftBracket)
409
+ let importSymbols = self.findModulesToImport(system, path, lspHook)
410
+ let o = CompletionHandler.handleCompletion(
411
+ lspHook = lspHook
412
+ toplevel = completionAt.column == 1
413
+ followedByOpenBracket = token.followedByLeftBracket
414
+ importSymbols = ImportSymbolsInfo(
415
+ import = toplevelToken.raw == "import" && location.column >= 8
416
+ importSymbols = importSymbols.first
417
+ importLine = importSymbols.second
418
+ )
419
+ )
399
420
  Result(o.write())
400
421
  }
401
422
 
@@ -592,7 +613,55 @@ extend self: Handler {
592
613
  None
593
614
  }
594
615
  }
595
-
616
+
617
+ findModulesToImport(system: NodeSystem, modulePath: Path, lspHook: LspHook): Pair[List[ImportSymbolInfo], Int] {
618
+ let importSymbols = if(self.importSymbolsCache.first == modulePath.absolute()) {
619
+ self.importSymbolsCache.second
620
+ } else {
621
+ let dependencies =
622
+ Dependencies.process(system.httpClient(), DependencyLock.new(system.mainTask()), modulePath)
623
+ let nonCore = dependencies.packagePaths.toList().filter {!_.first.isCore()}
624
+ function parseModule(packagePair: PackagePair, path: Path): Option[Module] {
625
+ dependencies.packagePaths.get(packagePair).flatMap: packagePath =>
626
+ packagePair.moduleKey(packagePath, path).flatMap: moduleKey =>
627
+ self.moduleCache.parsedModules.get(path.absolute()).map {_.first}.orElse:
628
+ try {
629
+ let code = self.virtualFiles.get(path.absolute()).else {path.readText()}
630
+ let tokens = Tokenizer.tokenize(path.absolute(), code, None, True)
631
+ let parser = Parser.new(moduleKey, tokens, True, LspHook.disabled())
632
+ parser.parseModuleWithPackageInfo().module
633
+ }.toOption()
634
+ }
635
+ let symbols = nonCore.flatMap {| Pair(packagePair, packagePath) =>
636
+ let packageFiles = Builder.findPackageFilesForDirectory(packagePath, None, Set.new())
637
+ packageFiles.flatMap {_.files.collect {file =>
638
+ parseModule(packagePair, file).map: module =>
639
+ let typeNames = module.types.map {_.name}
640
+ let variantNames = module.types.flatMap {_.variants.map {_.name}}
641
+ let traitNames = module.traits.map {_.name}
642
+ ImportSymbolInfo(module.moduleKey, typeNames, variantNames, traitNames)
643
+ }}
644
+ }
645
+ self.importSymbolsCache = Pair(modulePath.absolute(), symbols)
646
+ symbols
647
+ }
648
+ mutable importLine = 1
649
+ let imports = try {
650
+ let code = self.virtualFiles.get(modulePath.absolute()).else {modulePath.readText()}
651
+ let tokens = Tokenizer.tokenize(modulePath.absolute(), code, Some(lspHook.at), True)
652
+ let parser = Parser.new(ModuleKey(PackagePair("", ""), [], ""), tokens, True, lspHook)
653
+ tokens.each {token =>
654
+ if(token.is(LKeyword) && token.rawIs4("import", "include", "package", "dependency")) {
655
+ importLine = token.startLine + 1
656
+ }
657
+ }
658
+ parser.parseModuleWithPackageInfo().module
659
+ }.toOption().toList().flatMap {
660
+ _.imports.map {_.moduleKey}
661
+ }.toSet()
662
+ Pair(importSymbols.filter {!imports.contains(_.moduleKey)}, importLine)
663
+ }
664
+
596
665
  makeNotificationMessage(method: String, params: Json): Json {
597
666
  Json.object()
598
667
  .with("jsonrpc", "2.0")
@@ -38,6 +38,7 @@ main(system: NodeSystem) {
38
38
  cancelledRequests = [].toSet()
39
39
  responseCache = Map.new()
40
40
  fileSymbolsCache = Map.new()
41
+ importSymbolsCache = Pair("", [])
41
42
  moduleCache = cache
42
43
  dependencyLock = DependencyLock.new(system.mainTask())
43
44
  )
@@ -8,7 +8,7 @@ nodeMain(system: NodeSystem) {
8
8
  let fireflyPath = system.path(".")
9
9
  Log.debug(fireflyPath.absolute())
10
10
  let cache = ModuleCache.new(0)
11
- let handler = Handler(fireflyPath, None, Map.new(), [].toSet(), Map.new(), Map.new(), cache, DependencyLock.new(system.mainTask()))
11
+ let handler = Handler(fireflyPath, None, Map.new(), [].toSet(), Map.new(), Map.new(), Pair("", []), cache, DependencyLock.new(system.mainTask()))
12
12
  let targetAt = Location("/home/werk/projects/firefly-boot/lsp/TestReferencesCase.ff", 7, 5)
13
13
  let references = handler.findReferences(system, targetAt, local = False, includeDeclaration = True, version = 0)
14
14
  Log.show(references)
@@ -288,7 +288,12 @@ instances_.array.push(ff_compiler_Parser.Parser_parseInstanceDefinition(self_))
288
288
  } else if((ff_compiler_Token.Token_is(ff_compiler_Parser.Parser_current(self_), ff_compiler_Token.LKeyword()) && ff_compiler_Token.Token_rawIs4(ff_compiler_Parser.Parser_current(self_), "data", "class", "capability", "newtype"))) {
289
289
  types_.array.push(ff_compiler_Parser.Parser_parseTypeDefinition(self_))
290
290
  } else if((ff_compiler_Token.Token_is(ff_compiler_Parser.Parser_current(self_), ff_compiler_Token.LKeyword()) && ff_compiler_Token.Token_rawIs(ff_compiler_Parser.Parser_current(self_), "import"))) {
291
+ if(((ff_compiler_LspHook.LspHook_isEnabled(self_.lspHook_) && ff_compiler_Token.Token_is(ff_compiler_Parser.Parser_ahead(self_), ff_compiler_Token.LLower())) && (!ff_compiler_Token.Token_is(ff_compiler_Parser.Parser_aheadAhead(self_), ff_compiler_Token.LDot())))) {
292
+ ff_compiler_Parser.Parser_skip(self_, ff_compiler_Token.LKeyword());
293
+ ff_compiler_Parser.Parser_skip(self_, ff_compiler_Token.LLower())
294
+ } else {
291
295
  imports_.array.push(ff_compiler_Parser.Parser_parseImportDefinition(self_, self_.moduleKey_.packagePair_))
296
+ }
292
297
  } else if((ff_compiler_Token.Token_is(ff_compiler_Parser.Parser_current(self_), ff_compiler_Token.LKeyword()) && ff_compiler_Token.Token_rawIs(ff_compiler_Parser.Parser_current(self_), "include"))) {
293
298
  throw Object.assign(new Error(), {ffException: ff_core_Any.toAny_(ff_compiler_Syntax.CompileError(ff_compiler_Token.Token_at(ff_compiler_Parser.Parser_current(self_)), "Includes must be at the top of the file or below 'package'"), ff_compiler_Syntax.ff_core_Any_HasAnyTag$ff_compiler_Syntax_CompileError)})
294
299
  } else if((ff_compiler_Token.Token_is(ff_compiler_Parser.Parser_current(self_), ff_compiler_Token.LKeyword()) && ff_compiler_Token.Token_rawIs(ff_compiler_Parser.Parser_current(self_), "dependency"))) {
@@ -1792,7 +1797,12 @@ instances_.array.push(ff_compiler_Parser.Parser_parseInstanceDefinition(self_))
1792
1797
  } else if((ff_compiler_Token.Token_is(ff_compiler_Parser.Parser_current(self_), ff_compiler_Token.LKeyword()) && ff_compiler_Token.Token_rawIs4(ff_compiler_Parser.Parser_current(self_), "data", "class", "capability", "newtype"))) {
1793
1798
  types_.array.push(ff_compiler_Parser.Parser_parseTypeDefinition(self_))
1794
1799
  } else if((ff_compiler_Token.Token_is(ff_compiler_Parser.Parser_current(self_), ff_compiler_Token.LKeyword()) && ff_compiler_Token.Token_rawIs(ff_compiler_Parser.Parser_current(self_), "import"))) {
1800
+ if(((ff_compiler_LspHook.LspHook_isEnabled(self_.lspHook_) && ff_compiler_Token.Token_is(ff_compiler_Parser.Parser_ahead(self_), ff_compiler_Token.LLower())) && (!ff_compiler_Token.Token_is(ff_compiler_Parser.Parser_aheadAhead(self_), ff_compiler_Token.LDot())))) {
1801
+ ff_compiler_Parser.Parser_skip(self_, ff_compiler_Token.LKeyword());
1802
+ ff_compiler_Parser.Parser_skip(self_, ff_compiler_Token.LLower())
1803
+ } else {
1795
1804
  imports_.array.push(ff_compiler_Parser.Parser_parseImportDefinition(self_, self_.moduleKey_.packagePair_))
1805
+ }
1796
1806
  } else if((ff_compiler_Token.Token_is(ff_compiler_Parser.Parser_current(self_), ff_compiler_Token.LKeyword()) && ff_compiler_Token.Token_rawIs(ff_compiler_Parser.Parser_current(self_), "include"))) {
1797
1807
  throw Object.assign(new Error(), {ffException: ff_core_Any.toAny_(ff_compiler_Syntax.CompileError(ff_compiler_Token.Token_at(ff_compiler_Parser.Parser_current(self_)), "Includes must be at the top of the file or below 'package'"), ff_compiler_Syntax.ff_core_Any_HasAnyTag$ff_compiler_Syntax_CompileError)})
1798
1808
  } else if((ff_compiler_Token.Token_is(ff_compiler_Parser.Parser_current(self_), ff_compiler_Token.LKeyword()) && ff_compiler_Token.Token_rawIs(ff_compiler_Parser.Parser_current(self_), "dependency"))) {
package/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "description": "Firefly compiler",
5
5
  "author": "Firefly team",
6
6
  "license": "MIT",
7
- "version": "0.5.65",
7
+ "version": "0.5.66",
8
8
  "repository": {
9
9
  "type": "git",
10
10
  "url": "https://github.com/Ahnfelt/firefly-boot"
@@ -4,7 +4,7 @@
4
4
  "description": "Firefly language support",
5
5
  "author": "Firefly team",
6
6
  "license": "MIT",
7
- "version": "0.5.65",
7
+ "version": "0.5.66",
8
8
  "repository": {
9
9
  "type": "git",
10
10
  "url": "https://github.com/Ahnfelt/firefly-boot"
package/core/Box.ff DELETED
@@ -1,7 +0,0 @@
1
- class Box[T](mutable value: T)
2
-
3
- extend self[T]: Box[T] {
4
- modify(body: T => T): Unit {
5
- self.value = body(self.value)
6
- }
7
- }