diff options
Diffstat (limited to 'tex/context/base/mkxl/math-ini.lmt')
-rw-r--r-- | tex/context/base/mkxl/math-ini.lmt | 446 |
1 files changed, 276 insertions, 170 deletions
diff --git a/tex/context/base/mkxl/math-ini.lmt b/tex/context/base/mkxl/math-ini.lmt index 4ac76fa62..f41170a97 100644 --- a/tex/context/base/mkxl/math-ini.lmt +++ b/tex/context/base/mkxl/math-ini.lmt @@ -31,6 +31,8 @@ local ctx_doifelsesomething = commands.doifelsesomething local trace_defining = false trackers.register("math.defining", function(v) trace_defining = v end) +trace_defining = true + local report_math = logs.reporter("mathematics","initializing") mathematics = mathematics or { } @@ -47,86 +49,159 @@ local texsetattribute = tex.setattribute local setmathcode = tex.setmathcode local setdelcode = tex.setdelcode -local families = allocate { - mr = 0, - mb = 1, -} +-- These are different from mkiv with luatex. ---- to be checked .. a few defaults in char-def that should be alpha - -local classes = allocate { - ord = 0, -- mathordcomm mathord - op = 1, -- mathopcomm mathop - bin = 2, -- mathbincomm mathbin - rel = 3, -- mathrelcomm mathrel - open = 4, -- mathopencomm mathopen - middle = 4, - close = 5, -- mathclosecomm mathclose - punct = 6, -- mathpunctcomm mathpunct - alpha = 7, -- mathalphacomm firstofoneargument - accent = 8, -- class 0 - radical = 9, - xaccent = 10, -- class 3 - topaccent = 11, -- class 0 - botaccent = 12, -- class 0 - under = 13, - over = 14, - delimiter = 15, - inner = 0, -- mathinnercomm mathinner - nothing = 0, -- mathnothingcomm firstofoneargument - choice = 0, -- mathchoicecomm @@mathchoicecomm - box = 0, -- mathboxcomm @@mathboxcomm - limop = 1, -- mathlimopcomm @@mathlimopcomm - nolop = 1, -- mathnolopcomm @@mathnolopcomm - -- - ordinary = 0, -- ord - alphabetic = 7, -- alpha - unknown = 0, -- nothing - default = 0, -- nothing - punctuation = 6, -- punct - normal = 0, -- nothing - opening = 4, -- open - closing = 5, -- close - binary = 2, -- bin - relation = 3, -- rel - fence = 0, -- unknown - diacritic = 8, -- accent - large = 1, -- op - variable = 7, -- alphabetic - number = 7, -- alphabetic - root = 16, -- a private one +local classes = allocate { } +local classnames = allocate { } +local maxengineclass = 63 +local lastengineclass = 0 +local lastprivateclass = maxengineclass + +for k, v in next, nodes.noadcodes do + if type(k) == "string"then + classes[k] = v + local n = classnames[v] + if not n or #k < #n then + classnames[v] = k + end + elseif k > lastengineclass then + lastengineclass = k + end +end + +local ordinary_class = classes.ordinary +local operator_class = classes.operator +local binary_class = classes.binary +local relation_class = classes.relation +local open_class = classes.open +local close_class = classes.close +local punctuation_class = classes.punctuation +local middle_class = classes.middle +local accent_class = classes.accent +local radical_class = classes.radical +local fraction_class = classes.fraction +local under_class = classes.under +local over_class = classes.over +local fenced_class = classes.fenced +local ghost_class = classes.ghost + +classes.ord = ordinary_class +classes.op = operator_class +classes.bin = binary_class +classes.rel = relation_class +classes.opening = open_class -- will go +classes.closing = close_class -- will go +classes.punct = punctuation_class +classes.frac = fraction_class +classes.rad = radical_class +classes.fen = fenced_class +classes.gst = ghost_class + +classes.limop = operator_class +classes.limoperator = operator_class +classes.nolop = operator_class +classes.nolimoperator = operator_class +classes.large = operator_class +classes.largeoperator = operator_class + +-- special in the engine : variable active inner vcenter + +local function registerengineclass(name,short) + local class = classes[name] + if not class then + if lastengineclass < maxengineclass then + lastengineclass = lastengineclass + 1 + class = lastengineclass + classnames[class] = short or name + else + class = ordinary_class + end + classes[name] = class + end + return class +end + +local explicit_class = registerengineclass("explicit","expl") +local imaginary_class = registerengineclass("imaginary","im") +local diferential_class = registerengineclass("differential","dif") +local exponential_class = registerengineclass("exponential","exp") +local function_class = registerengineclass("function","fnc") +local digit_class = registerengineclass("digit","dig") +local division_class = registerengineclass("division","div") +local factorial_class = registerengineclass("factorial","fac") + +classes["begin"] = 62 classnames[62] = "begin" +classes["end"] = 63 classnames[63] = "end" + +local function registerprivateclass(name) + local class = classes[name] + if not class then + lastprivateclass = lastprivateclass + 1 + class = lastprivateclass + classes[name] = class + -- also setup + end + return class +end + +local function toengineclass(class) + if type(class) == "string" then + return classes[class] or ordinary_class + elseif class > lastengineclass then + return ordinary_class + else + return class + end +end + +implement { + name = "registerengineclass", + public = true, + protected = true, + arguments = { "optional", "optional" }, + actions = registerengineclass, } -local open_class = 4 -local middle_class = 4 -local close_class = 5 -local accent_class = 8 -local radical_class = 9 -local topaccent_class = 11 -local botaccent_class = 12 -local under_class = 13 -local over_class = 14 -local delimiter_class = 15 -local root_class = 16 +local topaccent_class = registerprivateclass("topaccent") +local botaccent_class = registerprivateclass("botaccent") +local delimiter_class = registerprivateclass("delimiter") +local root_class = registerprivateclass("root") +local prime_class = registerprivateclass("prime") local accents = allocate { accent = true, -- some can be both - topaccent = true, [11] = true, - botaccent = true, [12] = true, - under = true, [13] = true, - over = true, [14] = true, + topaccent = true, [topaccent_class] = true, + botaccent = true, [botaccent_class] = true, + under = true, [under_class] = true, + over = true, [over_class] = true, unknown = false, } +local integer_value = tokens.values.integer + +implement { + name = "mathclassvalue", + -- usage = "value", + public = true, + arguments = "string", + actions = function(name) + -- return integer_value, classes[name] or ordinary_class + context(tostring(classes[name] or ordinary_class)) + end +} + +-- used in math-tag: so there we need to make things ord etc to fit within +-- mathml + local codes = allocate { - ordinary = 0, [0] = "ordinary", - largeoperator = 1, "largeoperator", - binaryoperator = 2, "binaryoperator", - relation = 3, "relation", - openingsymbol = 4, "openingsymbol", - closingsymbol = 5, "closingsymbol", - punctuation = 6, "punctuation", - variable = 7, "variable", + ordinary = ordinary_class, [ordinary_class] = "ordinary", + largeoperator = operator_class, [operator_class] = "largeoperator", + binaryoperator = binary_class, [binary_class] = "binaryoperator", + relation = relation_class, [relation_class] = "relation", + openingsymbol = open_class, [open_class] = "openingsymbol", + closingsymbol = close_class, [close_class] = "closingsymbol", + punctuation = punctuation_class, [punctuation_class] = "punctuation", + middlesymbol = middle_class, [middle_class] = "middlesymbol", } local extensibles = allocate { @@ -169,61 +244,69 @@ function mathematics.virtualize(unicode,virtual) end end -mathematics.extensibles = extensibles -mathematics.classes = classes -mathematics.codes = codes ------------.accents = codes -mathematics.families = families -mathematics.virtualized = virtualized +mathematics.extensibles = extensibles +mathematics.classes = classes +mathematics.toengineclass = toengineclass +mathematics.classnames = classnames +mathematics.codes = codes +-----------.accents = codes +mathematics.virtualized = virtualized do - -- not that many so no need to reuse tables - local setmathcharacter = function(class,family,slot,unicode,mset,dset) - if mset and codes[class] then -- regular codes < 7 + if mset and class ~= ordinary_class then setmathcode("global",slot,class,family,unicode) mset = false end - if dset and class == open_class or class == close_class or class == middle_class then + if dset and (class == open_class or class == close_class or class == middle_class or class == division_class) then setdelcode("global",slot,family,unicode,0,0) dset = false end return mset, dset end - -- todo: make nice setters for this in lua + local function report(class,engine,family,unicode,name) + local nametype = type(name) + if nametype == "string" then + report_math("class %a, engine %a, family %a, char %C, name %a",class,engine,family,unicode,name) + elseif nametype == "number" then + report_math("class %a, engine %a, family %a, char %C, number %U",class,engine,family,unicode,name) + else + report_math("class %a, engine %a, family %a, char %C",class,engine,family,unicode) + end + end - local f_accent = formatters[ [[\defUmathtopaccent \%s{%X}{%X}{%X}]] ] - local f_topaccent = formatters[ [[\defUmathtopaccent \%s{%X}{%X}{%X}]] ] - local f_botaccent = formatters[ [[\defUmathbotaccent \%s{%X}{%X}{%X}]] ] - local f_over = formatters[ [[\defUdelimiterover \%s{%X}{%X}{%X}]] ] - local f_under = formatters[ [[\defUdelimiterunder\%s{%X}{%X}{%X}]] ] - local f_fence = formatters[ [[\defUdelimiter \%s{%X}{%X}{%X}]] ] - local f_delimiter = formatters[ [[\defUdelimiter \%s{%X}{%X}{%X}]] ] - local f_radical = formatters[ [[\defUradical \%s{%X}{%X}]] ] - local f_root = formatters[ [[\defUroot \%s{%X}{%X}]] ] - local f_char = formatters[ [[\defUmathchar \%s{%X}{%X}{%X}]] ] + local f_accent = formatters[ [[\defUmathtopaccent \%s{%X}{%X}{%X}]] ] + local f_fixedtopaccent = formatters[ [[\defUmathfixedtopaccent \%s{%X}{%X}{%X}]] ] + local f_fixedbotaccent = formatters[ [[\defUmathfixedbotaccent \%s{%X}{%X}{%X}]] ] + local f_topaccent = formatters[ [[\defUmathtopaccent \%s{%X}{%X}{%X}]] ] + local f_botaccent = formatters[ [[\defUmathbotaccent \%s{%X}{%X}{%X}]] ] + local f_over = formatters[ [[\defUdelimiterover \%s{%X}{%X}{%X}]] ] + local f_under = formatters[ [[\defUdelimiterunder\%s{%X}{%X}{%X}]] ] + local f_fence = formatters[ [[\defUdelimiter \%s{%X}{%X}{%X}]] ] + local f_delimiter = formatters[ [[\defUdelimiter \%s{%X}{%X}{%X}]] ] + local f_radical = formatters[ [[\defUradical \%s{%X}{%X}]] ] + local f_root = formatters[ [[\defUroot \%s{%X}{%X}]] ] + local f_char = formatters[ [[\defUmathchar \%s{%X}{%X}{%X}]] ] local texmathchardef = tex.mathchardef - local setmathsymbol = function(name,class,family,slot) -- hex is nicer for tracing + local setmathsymbol = function(name,class,engine,family,slot,stretch) -- hex is nicer for tracing if class == accent_class then ctx_sprint(f_topaccent(name,0,family,slot)) elseif class == topaccent_class then - ctx_sprint(f_topaccent(name,0,family,slot)) + ctx_sprint((stretch and f_topaccent or f_fixedtopaccent)(name,0,family,slot)) elseif class == botaccent_class then - ctx_sprint(f_botaccent(name,0,family,slot)) + ctx_sprint((stretch and f_botaccent or f_fixedbotaccent)(name,0,family,slot)) elseif class == over_class then ctx_sprint(f_over(name,0,family,slot)) elseif class == under_class then ctx_sprint(f_under(name,0,family,slot)) elseif class == open_class or class == close_class or class == middle_class then --- setdelcode("global",slot,{family,slot,0,0}) setdelcode("global",slot,family,slot,0,0) - ctx_sprint(f_fence(name,class,family,slot)) + ctx_sprint(f_fence(name,engine,family,slot)) elseif class == delimiter_class then --- setdelcode("global",slot,{family,slot,0,0}) setdelcode("global",slot,family,slot,0,0) ctx_sprint(f_delimiter(name,0,family,slot)) elseif class == radical_class then @@ -231,29 +314,31 @@ do elseif class == root_class then ctx_sprint(f_root(name,family,slot)) elseif texmathchardef then - texmathchardef(name,class,family,slot,"permanent") + texmathchardef(name,engine,family,slot,"permanent") else -- beware, open/close and other specials should not end up here - ctx_sprint(f_char(name,class,family,slot)) + ctx_sprint(f_char(name,engine,family,slot)) end end - local function report(class,family,unicode,name) - local nametype = type(name) - if nametype == "string" then - report_math("class name %a, class %a, family %a, char %C, name %a",classname,class,family,unicode,name) - elseif nametype == "number" then - report_math("class name %a, class %a, family %a, char %C, number %U",classname,class,family,unicode,name) - else - report_math("class name %a, class %a, family %a, char %C", classname,class,family,unicode) + function mathematics.define() + if trace_defining then + logs.startfilelogging(report_math,"math defined from character definitions") end - end - - -- there will be a combined \(math)chardef (tracker) - - function mathematics.define() -- we now always use family zero local family = 0 local data = characters.data + -- + local function remap(first,last) + for unicode=utfbyte(first),utfbyte(last) do + setmathcode("global",unicode,ordinary_class,family,unicode) + end + end + remap("0","9") + remap("A","Z") + remap("a","z") + -- + setdelcode("global",0x2E,0,0,0,0) -- period is special + -- for unicode, character in sortedhash(data) do local symbol = character.mathsymbol local mset = true @@ -262,11 +347,11 @@ do local other = data[symbol] local class = other.mathclass if class then - class = classes[class] or class -- no real checks needed + local engine = toengineclass(class) if trace_defining then - report(class,family,unicode,symbol) + report(class,engine,family,unicode,symbol) end - mset, dset = setmathcharacter(class,family,unicode,symbol,mset,dset) + mset, dset = setmathcharacter(engine,family,unicode,symbol,mset,dset) end local spec = other.mathspec if spec then @@ -274,84 +359,103 @@ do local m = spec[i] local class = m.class if class then - class = classes[class] or class -- no real checks needed - mset, dset = setmathcharacter(class,family,unicode,symbol,mset,dset) + local engine = toengineclass(class) + -- todo: trace + mset, dset = setmathcharacter(engine,family,unicode,symbol,mset,dset) end end end end - local mathclass = character.mathclass - local mathspec = character.mathspec - if mathspec then - if mathclass then - local name = character.mathname + local class = character.mathclass + local spec = character.mathspec + local name = character.mathname + local stretch = character.mathstretch + if spec then + local done = false + if class then if name then report_math("fatal error, conflicting mathclass and mathspec for %C",unicode) os.exit() else - local class = classes[mathclass] or mathclass -- no real checks needed - if not class then - if trace_defining then - report("unknown",family,unicode) - end - else - if trace_defining then - report(class,family,unicode) - end - mset, dset = setmathcharacter(class,family,unicode,unicode,mset,dset) + class = classes[class] or ordinary_class + local engine = toengineclass(class) + if trace_defining then + report(class,engine,family,unicode) end + mset, dset = setmathcharacter(engine,family,unicode,unicode,mset,dset) + done = true end end - for i=1,#mathspec do - local m = mathspec[i] - local name = m.name - local class = m.class + for i=1,#spec do + local m = spec[i] + local name = m.name + local class = m.class or class if class then - class = classes[class] or class -- no real checks needed + class = classes[class] or ordinary_class + else + class = ordinary_class + end + if class then + local engine = toengineclass(class) if name then if trace_defining then - report(class,family,unicode,name) + report(class,engine,family,unicode,name) end - setmathsymbol(name,class,family,unicode) + setmathsymbol(name,class,engine,family,unicode,stretch) else - name = (class == classes.variable or class == classes.number) and character.adobename -- bad + name = (class == classes.ordinary or class == classes.digit) and character.adobename -- bad if name and trace_defining then - report(class,family,unicode,name) + report(class,engine,family,unicode,name) end end - mset, dset = setmathcharacter(class,family,unicode,m.unicode or unicode,mset,dset) -- see solidus + if not done then + mset, dset = setmathcharacter(engine,family,unicode,m.unicode or unicode,mset,dset) -- see solidus + done = true + end end end - elseif mathclass then - local name = character.mathname - local class = classes[mathclass] or mathclass -- no real checks needed - if not class then - if trace_defining then - report("unknown",family,unicode,name) - end - elseif name == false then - if trace_defining then - report(class,family,unicode,name) - end - mset, dset = setmathcharacter(class,family,unicode,unicode,mset,dset) + else + if class then + class = classes[class] or ordinary_class else - -- if not name then - -- name = character.contextname -- too dangerous, we loose textslash and a few more - -- end - if name then + class = ordinary_class + end + if name ~= nil then + local engine = toengineclass(class) + if name == false then if trace_defining then - report(class,family,unicode,name) + report(class,engine,family,unicode,name) end - setmathsymbol(name,class,family,unicode) + mset, dset = setmathcharacter(engine,family,unicode,unicode,mset,dset) else - if trace_defining then - report(class,family,unicode,character.adobename) + -- if not name then + -- name = character.contextname -- too dangerous, we loose textslash and a few more + -- end + if name then + if trace_defining then + report(class,engine,family,unicode,name) + end + setmathsymbol(name,class,engine,family,unicode,stretch) + else + if trace_defining then + report(class,engine,family,unicode,character.adobename) + end end + mset, dset = setmathcharacter(engine,family,unicode,unicode,mset,dset) end - mset, dset = setmathcharacter(class,family,unicode,unicode,mset,dset) + elseif class ~= ordinary_class then + local engine = toengineclass(class) + if trace_defining then + report(class,engine,family,unicode,character.adobename) + end + mset, dset = setmathcharacter(engine,family,unicode,unicode,mset,dset) end end end + -- + if trace_defining then + logs.stopfilelogging() + end end end @@ -596,17 +700,19 @@ end -- 2: step 2 -- 3: htdp * 1.33^n -- 4: size * 1.33^n +-- 5: use lfg function mathematics.big(tfmdata,unicode,n,method) local t = tfmdata.characters local c = t[unicode] if c and n > 0 then - local vv = c.vvariants or c.next and t[c.next].vvariants - if vv then - local vvn = vv[n] - return vvn and vvn.glyph or vv[#vv].glyph or unicode - elseif method == 1 or method == 2 then - if method == 2 then -- large steps + if method == 1 or method == 2 or method == 5 then + if method == 5 then + local b = tfmdata.bigslots + if b then + n = (n > #b and b[#b]) or b[n] or n + end + elseif method == 2 then -- large steps n = n * 2 end local next = c.next @@ -754,7 +860,7 @@ implement { -- weird to do this here but it's a side affect of math anyway -interfaces.implement { +implement { name = "enableasciimode", onlyonce = true, actions = resolvers.macros.enablecomment, |