diff --git a/ace-modes.d.ts b/ace-modes.d.ts index 20a0c61c512..e1a88ebc78c 100644 --- a/ace-modes.d.ts +++ b/ace-modes.d.ts @@ -340,6 +340,12 @@ declare module "ace-code/src/mode/erlang" { declare module "ace-code/src/mode/erlang_highlight_rules" { export const ErlangHighlightRules: new () => import(".").Ace.HighlightRules; } +declare module "ace-code/src/mode/flix" { + export const Mode: new () => import(".").Ace.SyntaxMode; +} +declare module "ace-code/src/mode/flix_highlight_rules" { + export const FlixHighlightRules: new () => import(".").Ace.HighlightRules; +} declare module "ace-code/src/mode/forth" { export const Mode: new () => import(".").Ace.SyntaxMode; } diff --git a/demo/kitchen-sink/docs/flix.flix b/demo/kitchen-sink/docs/flix.flix new file mode 100644 index 00000000000..653f94cf9dd --- /dev/null +++ b/demo/kitchen-sink/docs/flix.flix @@ -0,0 +1,35 @@ +/// Mooo's `n` times on channel `c`. +def mooo(tx: Sender[String, r], n: Int32): Unit \ IO = + match n { + case 0 => () + case x => Channel.send("Mooo!", tx); mooo(tx, x - 1) + } + +/// Meow's `n` times on channel `c`. +def meow(tx: Sender[String, r], n: Int32): Unit \ IO = + match n { + case 0 => () + case x => Channel.send("Meow!", tx); meow(tx, x - 1) + } + +/// Hiss'es `n` times on channel `c`. +def hiss(tx: Sender[String, r], n: Int32): Unit \ IO = + match n { + case 0 => () + case x => Channel.send("Hiss!", tx); hiss(tx, x - 1) + } + +/// Start the animal farm... +def main(): Unit \ IO = region rc { + let (tx1, rx1) = Channel.buffered(rc, 10); + let (tx2, rx2) = Channel.buffered(rc, 10); + let (tx3, rx3) = Channel.buffered(rc, 10); + spawn mooo(tx1, 0) @ rc; + spawn meow(tx2, 3) @ rc; + spawn hiss(tx3, 7) @ rc; + select { + case m <- recv(rx1) => m |> println + case m <- recv(rx2) => m |> println + case m <- recv(rx3) => m |> println + } +} diff --git a/src/ext/modelist.js b/src/ext/modelist.js index b114c1e7975..6678f1e03b2 100644 --- a/src/ext/modelist.js +++ b/src/ext/modelist.js @@ -88,6 +88,7 @@ var supportedModes = { Elixir: ["ex|exs"], Elm: ["elm"], Erlang: ["erl|hrl"], + Flix: ["flix"], Forth: ["frt|fs|ldr|fth|4th"], Fortran: ["f|f90"], FSharp: ["fsi|fs|ml|mli|fsx|fsscript"], diff --git a/src/mode/_test/tokens_flix.json b/src/mode/_test/tokens_flix.json new file mode 100644 index 00000000000..2182c6d9a98 --- /dev/null +++ b/src/mode/_test/tokens_flix.json @@ -0,0 +1,293 @@ +[[ + "start", + ["text", " "] +],[ + "start", + ["comment.block", "/* Hello comment */"], + ["text", "\n"], + ["comment.block", "/* Hello \n comment */"], + ["text", "\n"], + ["comment.line", "// Hello comment"] +],[ + "start", + ["keyword", "use"], + ["text", " "], + ["identifier", "Add"], + ["text", "."], + ["identifier", "add"] +],[ + "start", + ["storage.type", "mod"], + ["text", " "], + ["paren.lparen", "{"], + ["storage.type", "def"], + ["text", " "], + ["identifier", "main"], + ["paren.lparen", "("], + ["paren.rparen", ")"], + ["text", ": "], + ["support.type", "Int32"], + ["text", " = "], + ["constant.numeric", "42"], + ["paren.rparen", "}"] +],[ + "start", + ["storage.type", "class"], + ["text", " "], + ["identifier", "Add"], + ["paren.lparen", "["], + ["identifier", "a"], + ["paren.rparen", "]"], + ["text", " "], + ["paren.lparen", "{"], + ["paren.rparen", "}"] +],[ + "start", + ["storage.type", "enum"], + ["text", " "], + ["identifier", "Down"], + ["paren.lparen", "["], + ["identifier", "a"], + ["paren.rparen", "]"], + ["text", " "], + ["storage.modifier", "with"], + ["text", " "], + ["identifier", "Sendable"], + ["text", " "], + ["paren.lparen", "{"], + ["storage.type", "case"], + ["text", " "], + ["identifier", "Down"], + ["paren.lparen", "("], + ["identifier", "a"], + ["paren.rparen", ")}"] +],[ + "start", + ["storage.type", "eff"], + ["text", " "], + ["identifier", "NonDet"] +],[ + "start", + ["storage.type", "type"], + ["text", " "], + ["storage.type", "alias"], + ["text", " "], + ["identifier", "Static"], + ["text", " = "], + ["identifier", "Impure"] +],[ + "start", + ["storage.type", "def"], + ["text", " "], + ["identifier", "main"], + ["paren.lparen", "("], + ["paren.rparen", ")"], + ["text", ": "], + ["support.type", "Int32"], + ["text", " = "], + ["paren.lparen", "{"], + ["constant.numeric", "42"], + ["paren.rparen", "}"] +],[ + "start", + ["storage.type", "def"], + ["text", " "], + ["identifier", "main"], + ["paren.lparen", "("], + ["paren.rparen", ")"], + ["text", ": "], + ["support.type", "Float64"], + ["text", " = "], + ["keyword.control", "if"], + ["paren.lparen", "("], + ["constant.language.boolean", "true"], + ["paren.rparen", ")"], + ["paren.lparen", "{"], + ["constant.numeric", "42.0"], + ["paren.rparen", "}"], + ["keyword.control", "else"], + ["paren.lparen", "{"], + ["constant.numeric", "43.0"], + ["paren.rparen", "}"] +],[ + "start", + ["storage.type", "def"], + ["text", " "], + ["identifier", "main"], + ["paren.lparen", "("], + ["paren.rparen", ")"], + ["text", ": "], + ["support.type", "String"], + ["text", " = "], + ["string", "\"Hello"], + ["constant.character.escape", "\\\""], + ["string", "World"], + ["constant.character.escape", "\\u0021"], + ["string", "\""] +],[ + "start", + ["storage.type", "def"], + ["text", " "], + ["identifier", "main"], + ["paren.lparen", "("], + ["paren.rparen", ")"], + ["text", ": "], + ["support.type", "Char"], + ["text", " = "], + ["constant.character", "'a'"] +],[ + "start", + ["storage.type", "def"], + ["text", " "], + ["identifier", "main"], + ["paren.lparen", "("], + ["paren.rparen", ")"], + ["text", ": "], + ["support.type", "Char"], + ["text", " = "], + ["constant.character", "'"], + ["constant.character.escape", "\\u0021"], + ["constant.character", "'"] +],[ + "start", + ["storage.type", "def"], + ["text", " "], + ["identifier", "main"], + ["paren.lparen", "("], + ["paren.rparen", ")"], + ["text", ": "], + ["support.type", "Char"], + ["text", " = "], + ["constant.character", "'"], + ["constant.character.escape", "\\'"], + ["constant.character", "'"] +],[ + "start", + ["storage.type", "def"], + ["text", " "], + ["identifier", "main"], + ["paren.lparen", "("], + ["paren.rparen", ")"], + ["text", ": "], + ["identifier", "Regex"], + ["text", " = "], + ["string.regexp", "regex\"Hello"], + ["constant.character.escape", "\\\""], + ["string.regexp", "World"], + ["constant.character.escape", "\\u0021"], + ["string.regexp", "\""] +],[ + "start", + ["storage.type", "def"], + ["text", " "], + ["identifier", "main"], + ["paren.lparen", "("], + ["paren.rparen", ")"], + ["text", ": "], + ["support.type", "String"], + ["text", " = "], + ["keyword", "???"] +],[ + "start", + ["storage.type", "def"], + ["text", " "], + ["identifier", "main"], + ["paren.lparen", "("], + ["paren.rparen", ")"], + ["text", ": "], + ["support.type", "String"], + ["text", " = "], + ["keyword", "?someHole"] +],[ + "start", + ["storage.type", "def"], + ["text", " "], + ["identifier", "main"], + ["paren.lparen", "("], + ["paren.rparen", ")"], + ["text", ": "], + ["support.type", "Int32"], + ["text", " = "], + ["constant.numeric", "0x123i32"] +],[ + "start", + ["storage.type", "def"], + ["text", " "], + ["identifier", "main"], + ["paren.lparen", "("], + ["paren.rparen", ")"], + ["text", ": "], + ["support.type", "Int32"], + ["text", " = "], + ["constant.numeric", "42i32"] +],[ + "start", + ["storage.type", "def"], + ["text", " "], + ["identifier", "main"], + ["paren.lparen", "("], + ["paren.rparen", ")"], + ["text", ": "], + ["support.type", "Float64"], + ["text", " = "], + ["constant.numeric", "42.0f64"] +],[ + "start", + ["storage.type", "def"], + ["text", " "], + ["identifier", "main"], + ["paren.lparen", "("], + ["paren.rparen", ")"], + ["text", ": "], + ["support.type", "Bool"], + ["text", " = "], + ["constant.language.boolean", "true"] +],[ + "start", + ["storage.type", "def"], + ["text", " "], + ["identifier", "main"], + ["paren.lparen", "("], + ["paren.rparen", ")"], + ["text", ": "], + ["support.type", "Bool"], + ["text", " = "], + ["constant.language.boolean", "false"] +],[ + "start", + ["storage.type", "def"], + ["text", " "], + ["identifier", "main"], + ["paren.lparen", "("], + ["paren.rparen", ")"], + ["text", ": "], + ["identifier", "Null"], + ["text", " = "], + ["constant.language", "null"] +],[ + "start", + ["storage.modifier", "@Lazy"], + ["text", "\n"], + ["storage.type", "def"], + ["text", " "], + ["identifier", "main"], + ["paren.lparen", "("], + ["paren.rparen", ")"], + ["text", ": "], + ["support.type", "Int32"], + ["text", " = "], + ["constant.numeric", "42"] +],[ + "start", + ["storage.modifier", "pub"], + ["text", " "], + ["storage.type", "def"], + ["text", " "], + ["identifier", "main"], + ["paren.lparen", "("], + ["paren.rparen", ")"], + ["text", ": "], + ["support.type", "Int32"], + ["text", " = "], + ["constant.numeric", "42"] +]] \ No newline at end of file diff --git a/src/mode/flix.js b/src/mode/flix.js new file mode 100644 index 00000000000..ac4c9630239 --- /dev/null +++ b/src/mode/flix.js @@ -0,0 +1,16 @@ +"use strict"; + +var oop = require("../lib/oop"); +var TextMode = require("./text").Mode; +var FlixHighlightRules = require("./flix_highlight_rules").FlixHighlightRules; + +var Mode = function() { + this.HighlightRules = FlixHighlightRules; +}; +oop.inherits(Mode, TextMode); + +(function() { + this.$id = "ace/mode/flix"; +}).call(Mode.prototype); + +exports.Mode = Mode; \ No newline at end of file diff --git a/src/mode/flix_highlight_rules.js b/src/mode/flix_highlight_rules.js new file mode 100644 index 00000000000..a5a67ce69b4 --- /dev/null +++ b/src/mode/flix_highlight_rules.js @@ -0,0 +1,152 @@ +"use strict"; + +var oop = require("../lib/oop"); +var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules; + +var FlixHighlightRules = function() { + + var keywords = ( + "use|checked_cast|checked_ecast|unchecked_cast|masked_cast|as|discard|from|" + + "into|inject|project|solve|query|where|select|force|import|region|red|deref" + ); + var controlKeywords = ( + "choose|debug|do|for|forA|forM|foreach|yield|if|else|case|" + + "match|typematch|try|catch|resume|spawn|par|branch|jumpto" + ); + var operators = "not|and|or|fix"; + var declarations = "eff|def|law|enum|case|type|alias|class|instance|mod|let"; + var modifiers = "with|without|opaque|lazy|lawful|pub|override|sealed|static"; + var primitives = "Unit|Bool|Char|Float32|Float64|Int8|Int16|Int32|Int64|BigInt|String"; + + var keywordMapper = this.createKeywordMapper({ + "keyword": keywords, + "keyword.control": controlKeywords, + "keyword.operator": operators, + "storage.type": declarations, + "storage.modifier": modifiers, + "support.type": primitives + }, "identifier"); + + this.$rules = { + "start" : [ + { + token : "comment.line", + regex : "\\/\\/.*$" + }, { + token : "comment.block", + regex : "\\/\\*", + next : "comment" + }, { + token : "string", + regex : '"', + next : "string" + }, { + token : "string.regexp", + regex : 'regex"', + next : "regex" + }, { + token : "constant.character", + regex : "'", + next : "char" + }, { + token : "constant.numeric", // hex + regex : "0x[a-fA-F0-9](_*[a-fA-F0-9])*(i8|i16|i32|i64|ii)?\\b" + }, { + token : "constant.numeric", // float + regex : "[0-9](_*[0-9])*\\.[0-9](_*[0-9])*(f32|f64)?\\b" + }, { + token : "constant.numeric", // integer + regex : "[0-9](_*[0-9])*(i8|i16|i32|i64|ii)?\\b" + }, { + token : "constant.language.boolean", + regex : "(true|false)\\b" + }, { + token : "constant.language", + regex : "null\\b" + }, { + token : "keyword.operator", + regex : "\\->|~>|<\\-|=>" + }, { + token : "storage.modifier", + regex : "@(Deprecated|Experimental|Internal|ParallelWhenPure|Parallel|LazyWhenPure|Lazy|Skip|Test)\\b" + }, { + token : "keyword", // hole + regex : "(\\?\\?\\?|\\?[a-zA-Z0-9]+)" + }, { + token : keywordMapper, + regex : "[a-zA-Z_$][a-zA-Z0-9_$]*\\b" + }, { + token : "paren.lparen", + regex : "[[({]" + }, { + token : "paren.rparen", + regex : "[\\])}]" + }, { + token : "text", + regex : "\\s+" + } + ], + "comment" : [ + { + token : "comment.block", + regex : "\\*\\/", + next : "start" + }, { + defaultToken : "comment.block" + } + ], + "string" : [ + { + token : "constant.character.escape", // unicode + regex : "\\\\(u[0-9a-fA-F]{4})" + }, { + token : "constant.character.escape", + regex : '\\\\.' + }, { + token : "string", + regex : '"', + next : "start" + }, { + token : "string", + regex : '[^"\\\\]+' + } + ], + "regex" : [ + { + token : "constant.character.escape", // unicode + regex : "\\\\(u[0-9a-fA-F]{4})" + }, { + token : "constant.character.escape", + regex : '\\\\.' + }, { + token : "string.regexp", + regex : '"', + next : "start" + }, { + token : "string.regexp", + regex : '[^"\\\\]+' + } + ], + "char" : [ + { + token : "constant.character.escape", // unicode + regex : "\\\\(u[0-9a-fA-F]{4})" + }, { + token : "constant.character.escape", + regex : '\\\\.' + }, { + token : "constant.character", + regex : "'", + next : "start" + }, { + token : "constant.character", + regex : "[^'\\\\]+" + } + ] + }; + +}; + +oop.inherits(FlixHighlightRules, TextHighlightRules); + +exports.FlixHighlightRules = FlixHighlightRules; \ No newline at end of file