Started adding DMs

This commit is contained in:
Louis Burke 2024-09-16 12:53:44 -04:00
parent 12b9a7a1be
commit c95ff6e188
2 changed files with 336 additions and 150 deletions

View file

@ -1,4 +1,5 @@
import dsl
import std/tables
# Tips: in python run
#
@ -80,7 +81,7 @@ dictionary:
# verb "be"
penta "n x", "Pronouns":
extremes i="Fully proximal", u="Fully distal"
extremes(i="Fully proximal", u="Fully distal")
i: pronoun "I/me"
e: pronoun "this"
@ -88,6 +89,9 @@ dictionary:
o: pronoun "it"
u: pronoun "that"
icosapenta "n t x", "Tests":
ii: noun "foo"
# TODO: Consider hepta scales as well? how?
when isMainModule:

480
dsl.nim
View file

@ -41,6 +41,7 @@ type
Word* = ref object
spelling*: string
definitions*: Table[PartOfSpeech, Definition]
derivations*: seq[Derivation]
Extremes* = object
i*: Option[string]
@ -63,12 +64,21 @@ type
first*: array[V, Penta]
second*: array[V, Penta]
DerivationalMorphology* = ref object
spelling*: string
definitions*: Table[PartOfSpeech, Definition]
Derivation* = ref object
root*: Word
dm*: DerivationalMorphology
Dictionary* = object
glyphs*: seq[Glyph]
dialects*: Table[string, seq[Replacement]]
words*: seq[Word]
pentas*: seq[Penta]
icosipentas*: seq[Icosapenta]
words*: Table[string, Word]
pentas*: Table[string, Penta]
icosapentas*: Table[string, Icosapenta]
dms*: Table[string, DerivationalMorphology]
const
Vowel2Char*: array[V, char] = [
@ -94,166 +104,294 @@ macro makeposprocs(): untyped =
for pos in PartOfSpeech:
let w = ident("w")
let defns = ident("definitions")
let name = ident(($pos).toLowerAscii)
let vpos = pos.newLit
result.add quote do:
proc `name`(short: string) {.used.} =
`w`.`defns`[`vpos`] = Definition(brief: short, long: string.none)
`w`.definitions[`vpos`] = Definition(brief: short, long: string.none)
proc `name`(short: string, long: string) {.used.} =
`w`.`defns`[`vpos`] = Definition(brief: short, long: long.some)
`w`.definitions[`vpos`] = Definition(brief: short, long: long.some)
macro makepentaprocs(): untyped =
result = nnkStmtList.newNimNode
for v in V:
let p = ident("p")
let name = ident("" & ($v).toLowerAscii[^1])
let val = v.newLit
result.add quote do:
template `name`(defns2: untyped) {.used.} =
edit_word `p`.elems[`val`]: defns2
macro make_icosaprocs(): untyped =
result = nnkStmtList.newNimNode
let ip = ident("ip")
# -x and x- templates
for v in V:
let namex = ident(($v).toLowerAscii[^1] & "x")
let xname = ident("x" & ($v).toLowerAscii[^1])
let val = v.newLit
result.add quote do:
template `namex`(defns2: untyped) {.used.} =
edit_penta `ip`.first[`val`]: defns2
template `xname`(defns2: untyped) {.used.} =
edit_penta `ip`.second[`val`]: defns2
# -- templates
for v1 in V:
for v2 in V:
let name = ident(($v1).toLowerAscii[^1] & ($v2).toLowerAscii[^1])
let val1 = v1.newLit
let name2 = ident("" & ($v2).toLowerAscii[^1])
result.add quote do:
template `name`(defns2: untyped) {.used.} =
edit_penta(`ip`.first[`val1`]):
`name2`: defns2
template glyph_dsl(dict: var Dictionary, gbody: untyped) =
block:
proc vowel(spelling: string, attrs: varargs[GlyphAttribute]) =
var v: Glyph = Glyph(spelling: spelling, kind: Vowel)
for attr in attrs:
v.attrs.incl attr
dict.glyphs.add v
proc cluster(spelling: string, attrs: varargs[GlyphAttribute]) =
var c: Glyph = Glyph(spelling: spelling, kind: Cluster)
for attr in attrs:
c.attrs.incl attr
dict.glyphs.add c
proc punctuation(spelling: string, attrs: varargs[GlyphAttribute]) =
var p: Glyph = Glyph(spelling: spelling, kind: Punctuation)
for attr in attrs:
p.attrs.incl attr
dict.glyphs.add p
proc numeric(spelling: string, attrs: varargs[GlyphAttribute]) =
var n: Glyph = Glyph(spelling: spelling, kind: Numeric)
for attr in attrs:
n.attrs.incl attr
dict.glyphs.add n
proc syllables() =
var newglyphs: seq[Glyph]
for v in dict.glyphs:
if v.kind != Vowel:
continue
for c in dict.glyphs:
if c.kind != Cluster:
continue
newglyphs.add Glyph(
spelling: c.spelling & v.spelling,
kind: Syllable,
attrs: v.attrs + c.attrs
)
dict.glyphs.add newglyphs
gbody
template dialect_dsl(dict: var Dictionary, name: string, dbody: untyped) =
block:
var dial: seq[Replacement]
proc replace(orig: string, by: string) =
dial.add Replacement(original: orig, replaced: by)
dbody
dict.dialects[name] = dial
template edit_word_dsl(theword: Word, defns: untyped) =
block:
var w {.inject.}: Word = theword
makeposprocs()
defns
template edit_dm_dsl(thedm: DerivationalMorphology, defns: untyped) =
block:
var w {.inject.}: DerivationalMorphology = thedm
makeposprocs()
defns
template words_dsl(dict: var Dictionary, wbody: untyped) =
block:
template edit_word(theword: Word, defns: untyped) =
edit_word_dsl(theword):
defns
template word(ortho: string, defns: untyped) =
block:
var w {.inject.} = Word(spelling: ortho)
proc via(root: string, dm: string) {.inject, used.} =
w.derivations.add Derivation(root: dict.words[root], dm: dict.dms[dm])
edit_word(w): defns
dict.words[w.spelling] = w
template edit_penta(thepenta: Penta, defns: untyped) =
block:
var p {.inject.}: Penta = thepenta
proc extremes(i {.inject.}: string, u {.inject.}: string) {.used.} =
p.exts.i = some(i)
p.exts.u = some(u)
makepentaprocs()
defns
template penta(ortho: string, pname: string, defns: untyped) =
block:
var p {.inject.}: Penta = Penta(
spelling: ortho,
name: pname,
exts: Extremes(i: string.none, u: string.none)
)
for v in V:
let spelling = ortho.replaceFirst(' ', Vowel2Char[v])
if spelling in dict.words:
p.elems[v] = dict.words[spelling]
else:
word ortho.replaceFirst(' ', Vowel2Char[v]):
p.elems[v] = w
edit_penta(p): defns
dict.pentas[ortho] = p
template edit_icosapenta(theicosa: Icosapenta, idefns: untyped) =
block:
var ip {.inject.}: Icosapenta = theicosa
proc firsts(i {.inject.}: string, u {.inject.}: string) {.used.} =
ip.exts.first.i = some(i)
ip.exts.first.u = some(u)
proc seconds(i {.inject.}: string, u {.inject.}: string) {.used.} =
ip.exts.second.i = some(i)
ip.exts.second.u = some(u)
template ix(defns2: untyped) {.used.} =
edit_penta ip.first[V_I]: defns2
template ex(defns2: untyped) {.used.} =
edit_penta ip.first[V_E]: defns2
template ax(defns2: untyped) {.used.} =
edit_penta ip.first[V_A]: defns2
template ox(defns2: untyped) {.used.} =
edit_penta ip.first[V_O]: defns2
template ux(defns2: untyped) {.used.} =
edit_penta ip.first[V_U]: defns2
template xi(defns2: untyped) {.used.} =
edit_penta ip.second[V_I]: defns2
template xe(defns2: untyped) {.used.} =
edit_penta ip.second[V_E]: defns2
template xa(defns2: untyped) {.used.} =
edit_penta ip.second[V_A]: defns2
template xo(defns2: untyped) {.used.} =
edit_penta ip.second[V_O]: defns2
template xu(defns2: untyped) {.used.} =
edit_penta ip.second[V_U]: defns2
make_icosaprocs()
# NOTE: first extremes is exts, second extremes is elems[*].exts
idefns
template icosapenta(iortho: string, iname: string, idefns: untyped) =
block:
var ip {.inject.}: Icosapenta = Icosapenta(
spelling: iortho,
name: iname,
exts: BiExtremes(
first: Extremes(i: string.none, u: string.none),
second: Extremes(i: string.none, u: string.none)
)
)
for v in V:
penta iortho.replaceFirst(' ', Vowel2Char[v]), Vowel2Char[v] & "x " & iname:
ip.first[v] = p
penta iortho.replaceLast(' ', Vowel2Char[v]), "x" & Vowel2Char[v] & " " & iname:
ip.second[v] = p
edit_icosapenta(ip): idefns
dict.icosapentas[iortho] = ip
template edit_dm(thedm: DerivationalMorphology, dmbody: untyped) =
edit_dm_dsl(thedm):
dmbody
template dm(ortho: string, defns: untyped) =
block:
var w {.inject.} = DerivationalMorphology(spelling: ortho)
edit_dm(w): defns
dict.dms[ortho] = w
wbody
template dictionary*(body: untyped) =
var dict {.inject.}: Dictionary
dict.glyphs = @[]
template glyphs(gbody: untyped) =
block:
proc vowel(spelling: string, attrs: varargs[GlyphAttribute]) =
var v: Glyph = Glyph(spelling: spelling, kind: Vowel)
for attr in attrs:
v.attrs.incl attr
dict.glyphs.add v
proc cluster(spelling: string, attrs: varargs[GlyphAttribute]) =
var c: Glyph = Glyph(spelling: spelling, kind: Cluster)
for attr in attrs:
c.attrs.incl attr
dict.glyphs.add c
proc punctuation(spelling: string, attrs: varargs[GlyphAttribute]) =
var p: Glyph = Glyph(spelling: spelling, kind: Punctuation)
for attr in attrs:
p.attrs.incl attr
dict.glyphs.add p
proc numeric(spelling: string, attrs: varargs[GlyphAttribute]) =
var n: Glyph = Glyph(spelling: spelling, kind: Numeric)
for attr in attrs:
n.attrs.incl attr
dict.glyphs.add n
proc syllables() =
var newglyphs: seq[Glyph]
for v in dict.glyphs:
if v.kind != Vowel:
continue
for c in dict.glyphs:
if c.kind != Cluster:
continue
newglyphs.add Glyph(
spelling: c.spelling & v.spelling,
kind: Syllable,
attrs: v.attrs + c.attrs
)
dict.glyphs.add newglyphs
glyph_dsl(dict):
gbody
template dialect(name: string, dbody: untyped) =
block:
var dial: seq[Replacement]
proc replace(orig: string, by: string) =
dial.add Replacement(original: orig, replaced: by)
dialect_dsl(dict, name):
dbody
dict.dialects[name] = dial
# TODO: add a words: proc to create and return a dm, so that within words
# you can use it
# e.g.
#
# words:
# let foo = dm "example-":
# noun "does something to nouns"
#
# word "example1":
# noun "does something once to nouns"
# by "1" via foo
# # or maybe?
# foo["1"]
template words(wbody: untyped) =
block:
template word(ortho: string, defns: untyped) =
block:
var w {.inject.} = Word(spelling: ortho)
makeposprocs()
defns
dict.words.add w
template edit_word(theword: Word, defns: untyped) =
block:
var w {.inject.}: Word = theword
makeposprocs()
defns
template penta(ortho: string, pname: string, defns: untyped) =
block:
var p {.inject.}: Penta = Penta(
spelling: ortho,
name: pname,
exts: Extremes(i: string.none, u: string.none)
)
for v in V:
word ortho.replaceFirst(' ', Vowel2Char[v]):
p.elems[v] = w
proc extremes(i {.inject.}: string, u {.inject.}: string) {.used.} =
p.exts.i = some(i)
p.exts.u = some(u)
template i(defns2: untyped) {.used.} =
edit_word p.elems[V_I]: defns2
template e(defns2: untyped) {.used.} =
edit_word p.elems[V_E]: defns2
template a(defns2: untyped) {.used.} =
edit_word p.elems[V_A]: defns2
template o(defns2: untyped) {.used.} =
edit_word p.elems[V_O]: defns2
template u(defns2: untyped) {.used.} =
edit_word p.elems[V_U]: defns2
defns
dict.pentas.add p
template icosipenta(iortho: string, iname: string, idefns: untyped) =
block:
var i {.inject.}: Icosapenta = Icosapenta(
spelling: iortho,
name: iname,
exts: BiExtremes(
first: Extremes(i: string.none, u: string.none),
second: Extremes(i: string.none, u: string.none)
)
)
for v in V:
penta iortho.replaceFirst(' ', Vowel2Char[v]), Vowel2Char[v] & "x " & iname:
i.first[v] = p
penta iortho.replaceLast(' ', Vowel2Char[v]), "x" & Vowel2Char[v] & " " & iname:
i.second[v] = p
proc firsts(i {.inject.}: string, u {.inject.}: string) {.used.} =
i.exts.first.i = some(i)
i.exts.first.u = some(u)
proc seconds(i {.inject.}: string, u {.inject.}: string) {.used.} =
i.exts.second.i = some(i)
i.exts.second.u = some(u)
template ix(defns2: untyped) {.used.} =
edit_penta i.first[V_I]: defns2
# TODO: rest of the -x and x-, plus write edit_penta
template ii(defns2: untyped) {.used.} =
edit_word i.first[V_I].elems[V_I]: defns2
# TODO: check that this also edits i.second[V_I].elems[V_I]
# TODO: rest of the --
# NOTE: first extremes is exts, second extremes is elems[*].exts
words_dsl(dict):
wbody
body
@ -287,19 +425,45 @@ proc toJsonHook(exts: Extremes): JsonNode =
result["u"] = newJString(exts.u.get)
proc toJson(penta: Penta, dict: Dictionary): JsonNode =
proc toJson(penta: Penta): JsonNode =
result = newJObject()
result["extremes"] = penta.exts.toJson
result["name"] = newJString(penta.name)
# TODO: Consider looking up i/e/a/o/u in dict
proc toJson(pentas: seq[Penta], dict: Dictionary): JsonNode =
proc toJson(pentas: seq[Penta]): JsonNode =
result = newJObject()
for penta in pentas:
result[penta.spelling] = penta.toJson(dict)
result[penta.spelling] = penta.toJson
proc toJson(exts: BiExtremes): JsonNode =
result = newJObject()
if exts.first.i.isSome:
result["ix"] = newJString(exts.first.i.get)
if exts.first.u.isSome:
result["ux"] = newJString(exts.first.u.get)
if exts.second.i.isSome:
result["xi"] = newJString(exts.second.i.get)
if exts.second.u.isSome:
result["xu"] = newJString(exts.second.u.get)
proc toJson(icosa: Icosapenta): JsonNode =
result = newJObject()
result["extremes"] = icosa.exts.toJson
result["name"] = newJString(icosa.name)
proc toJson(icosas: seq[Icosapenta]): JsonNode =
result = newJObject()
for icosa in icosas:
result[icosa.spelling] = icosa.toJson
proc toJsonHook(dict: Dictionary): JsonNode =
@ -307,12 +471,18 @@ proc toJsonHook(dict: Dictionary): JsonNode =
result["glyphs"] = dict.glyphs.toJson
result["dialects"] = dict.dialects.toJson
result["words"] = dict.words.toJson
result["pentas"] = dict.pentas.toJson(dict)
result["words"] = dict.words.values.toSeq.toJson
result["pentas"] = dict.pentas.toJson
result["icosas"] = dict.icosapentas.toJson
proc jsonify*(dict: Dictionary): string =
return $(dict.toJson)
proc `$`*(word: Word): string =
if word.definitions.len > 0:
return word.spelling & "(" & word.definitions.pairs.toSeq.map(proc(p: (PartOfSpeech, Definition)): string = $p[0] & ":" & p[1].brief).join(",") & ")"
return word.spelling
when isMainModule:
dictionary:
glyphs:
@ -335,6 +505,9 @@ when isMainModule:
replace "k", "g"
words:
dm "foo-":
noun "fooish"
word "t":
noun "thing", "See t - dmPenta for better meaning."
# verb "be"
@ -344,4 +517,13 @@ when isMainModule:
i: pronoun "I/me"
icosapenta "n t t", "Tests":
ii: verb "foo"
word "foot":
noun "fooish thing"
via("t", "foo-")
# "t".via "foo-"
echo dict.jsonify