From a0c7a5fc0f61fdcf75bcfe23f5114e6d961032f6 Mon Sep 17 00:00:00 2001 From: pzinn Date: Thu, 28 Nov 2024 13:37:32 +1100 Subject: [PATCH 01/14] 1st attempt: m2 level makeKeyword --- M2/Macaulay2/d/actors5.d | 10 ++++++++++ M2/Macaulay2/d/binding.d | 7 +++++-- M2/Macaulay2/d/convertr.d | 17 ++++++++++++++--- M2/Macaulay2/d/evaluate.d | 9 +++++++++ M2/Macaulay2/m2/exports.m2 | 1 + 5 files changed, 39 insertions(+), 5 deletions(-) diff --git a/M2/Macaulay2/d/actors5.d b/M2/Macaulay2/d/actors5.d index 1c15f103dae..af1ac01285e 100644 --- a/M2/Macaulay2/d/actors5.d +++ b/M2/Macaulay2/d/actors5.d @@ -1,6 +1,7 @@ -- Copyright 1995,2010 by Daniel R. Grayson use actors; use actors2; +use binding; header "#include "; @@ -13,6 +14,15 @@ getParsing(e:Expr):Expr := ( else nullE); setupfun("getParsing",getParsing); +export makeKeywordFun(e:Expr):Expr := ( + when e + is s:stringCell do ( + Expr(makeKeyword(binaryleft(s.v))) -- TODO check whether install is really needed (for mathematical symbols as opposed to words) + ) + else nullE -- TODO error (but anyway won't be called directly) + ); +setupfun("makeKeyword",makeKeywordFun); + LongDoubleRightArrowFun(lhs:Code,rhs:Code):Expr := binarymethod(lhs,rhs,LongDoubleRightArrowS); setup(LongDoubleRightArrowS,LongDoubleRightArrowFun); diff --git a/M2/Macaulay2/d/binding.d b/M2/Macaulay2/d/binding.d index f4b4985e516..0bab20b7ad1 100644 --- a/M2/Macaulay2/d/binding.d +++ b/M2/Macaulay2/d/binding.d @@ -137,7 +137,7 @@ export makeProtectedSymbolClosure(w:Word):SymbolClosure := ( when globalFrame.values.(entry.frameindex) is s:SymbolClosure do s else SymbolClosure(globalFrame,entry)); -makeKeyword(w:Word):SymbolClosure := ( +export makeKeyword(w:Word):SymbolClosure := ( -- keywords differ from symbols in that their initial value is null entry := makeEntry(w,dummyPosition,globalDictionary); entry.Protected = true; @@ -157,7 +157,7 @@ unaryword(s:string) :Word := makeUniqueWord(s, parseinfo(prec,nopr postfix(s:string) :Word := install(s,makeUniqueWord(s, parseinfo(prec,nopr ,nopr,parsefuns(errorunary,postfixop)))); unarybinaryleft(s:string) :Word := install(s,makeUniqueWord(s, parseinfo(prec,prec ,prec,parsefuns(unaryop ,binaryop)))); unarybinaryright(s:string) :Word := install(s,makeUniqueWord(s, parseinfo(prec,prec-1,prec,parsefuns(unaryop ,binaryop)))); -binaryleft(s:string) :Word := install(s,makeUniqueWord(s, parseinfo(prec,prec ,nopr,parsefuns(errorunary,binaryop)))); +export binaryleft(s:string) :Word := install(s,makeUniqueWord(s, parseinfo(prec,prec ,nopr,parsefuns(errorunary,binaryop)))); nright(s:string) :Word := install(s,makeUniqueWord(s, parseinfo(prec,prec-1,nopr,parsefuns(errorunary,nbinaryop)))); nleftword(s:string) :Word := makeUniqueWord(s, parseinfo(prec,prec ,nopr,parsefuns(errorunary,nbinaryop))); nunarybinaryleft(s:string) :Word := install(s,makeUniqueWord(s, parseinfo(prec,prec ,prec,parsefuns(nnunaryop ,nbinaryop)))); @@ -644,14 +644,17 @@ bindParenParmList(e:ParseTree,dictionary:Dictionary,desc:functionDescription):vo is p:EmptyParentheses do nothing else makeErrorTree(e,"expected parenthesized argument list or symbol")); opHasBinaryMethod(o:Symbol):bool := ( + return true; -- TEMP foreach s in opsWithBinaryMethod do if s.symbol == o then return true; return false; ); opHasUnaryMethod(o:Symbol):bool := ( + return true; -- TEMP foreach s in opsWithUnaryMethod do if s.symbol == o then return true; return false; ); opHasPostfixMethod(o:Symbol):bool := ( + return true; -- TEMP foreach s in opsWithPostfixMethod do if s.symbol == o then return true; return false; ); diff --git a/M2/Macaulay2/d/convertr.d b/M2/Macaulay2/d/convertr.d index b3a9d3e7221..e4e5bed21bb 100644 --- a/M2/Macaulay2/d/convertr.d +++ b/M2/Macaulay2/d/convertr.d @@ -21,6 +21,8 @@ export UnaryInstallMethodFun := dummyTernaryFun; export InstallValueFun := dummyMultaryFun; export UnaryInstallValueFun := dummyTernaryFun; +export binarymethod1 := dummyTernaryFun; -- temporary, will be redefined in evaluate.d + convert(e:ParseTree):Code; CodeSequenceLength(e:ParseTree,separator:Word):int := ( i := 0; @@ -189,7 +191,12 @@ export convert0(e:ParseTree):Code := ( rhs := convertGlobalOperator(token); -- TODO: is this check necessary? if token.word.typecode == TCid - then Code(binaryCode(b.Operator.entry.binary, convert(b.lhs), rhs, pos)) + then ( + f:=b.Operator.entry.binary; if f==dummyBinaryFun then + Code(ternaryCode(binarymethod1,convert(b.lhs), rhs, globalSymbolClosureCode(b.Operator.entry, dummyPosition),pos)) + else + Code(binaryCode(f, convert(b.lhs), rhs, pos)) + ) else dummyCode -- should not occur ) else dummyCode -- should not occur @@ -300,8 +307,12 @@ export convert0(e:ParseTree):Code := ( else Code(augmentedAssignmentCode( b.Operator.entry, dummyCode, dummyCode, dummySymbol, dummyPosition)) -- CHECK ) - else Code(binaryCode(b.Operator.entry.binary, convert(b.lhs), convert(b.rhs), pos)) - ) + else ( + f:=b.Operator.entry.binary; if f==dummyBinaryFun then + Code(ternaryCode(binarymethod1,convert(b.lhs), convert(b.rhs), globalSymbolClosureCode(b.Operator.entry, dummyPosition),pos)) + else + Code(binaryCode(f, convert(b.lhs), convert(b.rhs), pos)) + )) is u:Unary do ( if u.Operator.word == CommaW then Code(sequenceCode(makeCodeSequence(e, CommaW), pos)) else if u.Operator.word == SemicolonW then Code(semiCode( makeCodeSequence(e, SemicolonW), pos)) diff --git a/M2/Macaulay2/d/evaluate.d b/M2/Macaulay2/d/evaluate.d index 8c4629f4cbe..e7f5009d9db 100644 --- a/M2/Macaulay2/d/evaluate.d +++ b/M2/Macaulay2/d/evaluate.d @@ -1095,6 +1095,7 @@ export unarymethod(rhs:Code,methodkey:SymbolClosure):Expr := ( method := lookup(Class(right),Expr(methodkey),methodkey.symbol.hash); if method == nullE then MissingMethod(methodkey) else applyEE(method,right))); + export binarymethod(lhs:Code,rhs:Code,methodkey:SymbolClosure):Expr := ( left := eval(lhs); when left is Error do left @@ -1119,6 +1120,12 @@ export binarymethod(left:Expr,rhs:Code,methodkey:SymbolClosure):Expr := ( else MissingMethodPair(methodkey,left,right) ) else applyEEE(method,left,right))); +export binarymethodCode(lhs:Code,rhs:Code,methodkey:Code):Expr := ( + when methodkey is + s:globalSymbolClosureCode do binarymethod(lhs,rhs,SymbolClosure(globalFrame,s.symbol)) + else nullE +); + ----------------------------------------------------------------------------- @@ -2110,6 +2117,8 @@ nullCoalescion(lhs:Code,rhs:Code):Expr := ( else e); setup(QuestionQuestionS, nullify, nullCoalescion); +binarymethod1=binarymethodCode; + -- Local Variables: -- compile-command: "echo \"make: Entering directory \\`$M2BUILDDIR/Macaulay2/d'\" && make -C $M2BUILDDIR/Macaulay2/d evaluate.o " -- End: diff --git a/M2/Macaulay2/m2/exports.m2 b/M2/Macaulay2/m2/exports.m2 index bdd7f479a22..a1dd5453ffd 100644 --- a/M2/Macaulay2/m2/exports.m2 +++ b/M2/Macaulay2/m2/exports.m2 @@ -896,6 +896,7 @@ export { "lookup", "lookupCount", "makeDirectory", + "makeKeyword", "makeDocumentTag", "makePackageIndex", "map", From 092541f0cf53e46df266a28e4ff404c1e13cbb48 Mon Sep 17 00:00:00 2001 From: pzinn Date: Thu, 28 Nov 2024 20:27:57 +1100 Subject: [PATCH 02/14] start actors5.d cleanup --- M2/Macaulay2/d/actors5.d | 131 -------------------------------------- M2/Macaulay2/d/convertr.d | 17 ++++- M2/Macaulay2/d/evaluate.d | 6 ++ 3 files changed, 21 insertions(+), 133 deletions(-) diff --git a/M2/Macaulay2/d/actors5.d b/M2/Macaulay2/d/actors5.d index af1ac01285e..0f100b9a6c4 100644 --- a/M2/Macaulay2/d/actors5.d +++ b/M2/Macaulay2/d/actors5.d @@ -23,27 +23,6 @@ export makeKeywordFun(e:Expr):Expr := ( ); setupfun("makeKeyword",makeKeywordFun); -LongDoubleRightArrowFun(lhs:Code,rhs:Code):Expr := binarymethod(lhs,rhs,LongDoubleRightArrowS); -setup(LongDoubleRightArrowS,LongDoubleRightArrowFun); - -LongLongDoubleRightArrowFun(lhs:Code,rhs:Code):Expr := binarymethod(lhs,rhs,LongLongDoubleRightArrowS); -setup(LongLongDoubleRightArrowS,LongLongDoubleRightArrowFun); - -LongDoubleLeftArrowFun1(rhs:Code):Expr := unarymethod(rhs,LongDoubleLeftArrowS); -LongDoubleLeftArrowFun2(lhs:Code,rhs:Code):Expr := binarymethod(lhs,rhs,LongDoubleLeftArrowS); -setup(LongDoubleLeftArrowS,LongDoubleLeftArrowFun1,LongDoubleLeftArrowFun2); - -LongLongDoubleLeftArrowFun1(rhs:Code):Expr := unarymethod(rhs,LongLongDoubleLeftArrowS); -LongLongDoubleLeftArrowFun2(lhs:Code,rhs:Code):Expr := binarymethod(lhs,rhs,LongLongDoubleLeftArrowS); -setup(LongLongDoubleLeftArrowS,LongLongDoubleLeftArrowFun1,LongLongDoubleLeftArrowFun2); - -LongBiDoubleArrowFun(lhs:Code,rhs:Code):Expr := binarymethod(lhs,rhs,LongBiDoubleArrowS); -setup(LongBiDoubleArrowS,LongBiDoubleArrowFun); - -binaryDeductionFun(lhs:Code,rhs:Code):Expr := binarymethod(lhs,rhs,DeductionS); -unaryDeductionFun(rhs:Code):Expr := unarymethod(rhs,DeductionS); -setup(DeductionS,unaryDeductionFun,binaryDeductionFun); - -- doublePointerfun(lhs:Code,rhs:Code):Expr := binarymethod(lhs,rhs,DoubleArrowS); optionFun(lhs:Code,rhs:Code):Expr := ( -- # typical value: symbol =>, Thing, Thing, Option @@ -147,108 +126,6 @@ integermod(e:Expr):Expr := ( else WrongNumArgs(2)); installMethod(PercentS,ZZClass,ZZClass,integermod); -modC(lhs:Code,rhs:Code):Expr := binarymethod(lhs,rhs,PercentS); -setup(PercentS,modC); - -AtAtfun(lhs:Code,rhs:Code):Expr := binarymethod(lhs,rhs,AtAtS); -setup(AtAtS,AtAtfun); - -StarStarfun(lhs:Code,rhs:Code):Expr := binarymethod(lhs,rhs,StarStarS); -setup(StarStarS,StarStarfun); - -doubleplusfun(lhs:Code,rhs:Code):Expr := binarymethod(lhs,rhs,PlusPlusS); -setup(PlusPlusS,doubleplusfun); - -lesslessfun2(lhs:Code,rhs:Code):Expr := binarymethod(lhs,rhs,LessLessS); -lesslessfun1(rhs:Code):Expr := unarymethod(rhs,LessLessS); -setup(LessLessS,lesslessfun1,lesslessfun2); - -greatergreaterfun2(lhs:Code,rhs:Code):Expr := binarymethod(lhs,rhs,GreaterGreaterS); -setup(GreaterGreaterS,greatergreaterfun2); - -barfun(lhs:Code,rhs:Code):Expr := binarymethod(lhs,rhs,BarS); -setup(BarS,barfun); - -BarUnderscorefun(lhs:Code,rhs:Code):Expr := binarymethod(lhs,rhs,BarUnderscoreS); -setup(BarUnderscoreS,BarUnderscorefun); - -UnderscoreGreaterfun(lhs:Code,rhs:Code):Expr := binarymethod(lhs,rhs,UnderscoreGreaterS); -setup(UnderscoreGreaterS,UnderscoreGreaterfun); - -UnderscoreGreaterEqualfun(lhs:Code,rhs:Code):Expr := binarymethod(lhs,rhs,UnderscoreGreaterEqualS); -setup(UnderscoreGreaterEqualS,UnderscoreGreaterEqualfun); - -UnderscoreLessfun(lhs:Code,rhs:Code):Expr := binarymethod(lhs,rhs,UnderscoreLessS); -setup(UnderscoreLessS,UnderscoreLessfun); - -UnderscoreLessEqualfun(lhs:Code,rhs:Code):Expr := binarymethod(lhs,rhs,UnderscoreLessEqualS); -setup(UnderscoreLessEqualS,UnderscoreLessEqualfun); - -PowerGreaterfun(lhs:Code,rhs:Code):Expr := binarymethod(lhs,rhs,PowerGreaterS); -setup(PowerGreaterS,PowerGreaterfun); - -PowerGreaterEqualfun(lhs:Code,rhs:Code):Expr := binarymethod(lhs,rhs,PowerGreaterEqualS); -setup(PowerGreaterEqualS,PowerGreaterEqualfun); - -PowerLessfun(lhs:Code,rhs:Code):Expr := binarymethod(lhs,rhs,PowerLessS); -setup(PowerLessS,PowerLessfun); - -PowerLessEqualfun(lhs:Code,rhs:Code):Expr := binarymethod(lhs,rhs,PowerLessEqualS); -setup(PowerLessEqualS,PowerLessEqualfun); - -PowerStarStarfun(lhs:Code,rhs:Code):Expr := binarymethod(lhs,rhs,PowerStarStarS); -setup(PowerStarStarS,PowerStarStarfun); - -colonfun(lhs:Code,rhs:Code):Expr := binarymethod(lhs,rhs,ColonS); -setup(ColonS,colonfun); - -ampersandfun(lhs:Code,rhs:Code):Expr := binarymethod(lhs,rhs,AmpersandS); -setup(AmpersandS,ampersandfun); - -hathatfun(lhs:Code,rhs:Code):Expr := binarymethod(lhs,rhs,HatHatS); -setup(HatHatS,hathatfun); - -interpunctfun(lhs:Code, rhs:Code):Expr := binarymethod(lhs, rhs, InterpunctS); -setup(InterpunctS, interpunctfun); - -boxtimesfun(lhs:Code, rhs:Code):Expr := binarymethod(lhs, rhs, BoxTimesS); -setup(BoxTimesS, boxtimesfun); - -shuffleproductfun(lhs:Code, rhs:Code):Expr := binarymethod(lhs, rhs, ShuffleProductS); -setup(ShuffleProductS, shuffleproductfun); - -Tildefun(rhs:Code):Expr := unarymethod(rhs,TildeS); -setuppostfix(TildeS,Tildefun); - -PowerTildefun(rhs:Code):Expr := unarymethod(rhs,PowerTildeS); -setuppostfix(PowerTildeS,PowerTildefun); - -UnderscoreTildefun(rhs:Code):Expr := unarymethod(rhs,UnderscoreTildeS); -setuppostfix(UnderscoreTildeS,UnderscoreTildefun); - -ParenStarParenfun(rhs:Code):Expr := unarymethod(rhs,ParenStarParenS); -setuppostfix(ParenStarParenS,ParenStarParenfun); - -UnderscoreStarfun(rhs:Code):Expr := unarymethod(rhs,UnderscoreStarS); -setuppostfix(UnderscoreStarS,UnderscoreStarfun); - -PowerStarfun(rhs:Code):Expr := unarymethod(rhs,PowerStarS); -setuppostfix(PowerStarS,PowerStarfun); - ---PowerSharpfun(rhs:Code):Expr := unarymethod(rhs,PowerSharpS); ---setuppostfix(PowerSharpS,PowerSharpfun); - ---UnderscoreSharpfun(rhs:Code):Expr := unarymethod(rhs,UnderscoreSharpS); ---setuppostfix(UnderscoreSharpS,UnderscoreSharpfun); - -Exclamationfun(rhs:Code):Expr := unarymethod(rhs,ExclamationS); -setuppostfix(ExclamationS,Exclamationfun); - -PowerExclamationfun(rhs:Code):Expr := unarymethod(rhs,PowerExclamationS); -setuppostfix(PowerExclamationS,PowerExclamationfun); - -UnderscoreExclamationfun(rhs:Code):Expr := unarymethod(rhs,UnderscoreExclamationS); -setuppostfix(UnderscoreExclamationS,UnderscoreExclamationfun); factorial(x:Expr):Expr := ( when x @@ -266,9 +143,6 @@ installMethod(ExclamationS,RRClass,factorial); installMethod(ExclamationS,ZZClass,factorial); installMethod(ExclamationS,QQClass,factorial); -underscorefun(lhs:Code,rhs:Code):Expr := binarymethod(lhs,rhs,UnderscoreS); -setup(UnderscoreS,underscorefun); - dotfun(lhs:Code,rhs:Code):Expr := ( left := eval(lhs); when left is Error do left @@ -290,11 +164,6 @@ dotQfun(lhs:Code,rhs:Code):Expr := ( else False); setup(DotQuestionS,dotQfun); -atfun(lhs:Code,rhs:Code):Expr := binarymethod(lhs,rhs,AtS); -setup(AtS,atfun); - -leftDividefun(lhs:Code,rhs:Code):Expr := binarymethod(lhs,rhs,LeftDivideS); -setup(LeftDivideS,leftDividefun); header " #ifdef HAVE_SYS_IOCTL_H diff --git a/M2/Macaulay2/d/convertr.d b/M2/Macaulay2/d/convertr.d index e4e5bed21bb..cc58a1b0a2e 100644 --- a/M2/Macaulay2/d/convertr.d +++ b/M2/Macaulay2/d/convertr.d @@ -22,6 +22,7 @@ export InstallValueFun := dummyMultaryFun; export UnaryInstallValueFun := dummyTernaryFun; export binarymethod1 := dummyTernaryFun; -- temporary, will be redefined in evaluate.d +export unarymethod1 := dummyBinaryFun; -- temporary, will be redefined in evaluate.d convert(e:ParseTree):Code; CodeSequenceLength(e:ParseTree,separator:Word):int := ( @@ -316,8 +317,20 @@ export convert0(e:ParseTree):Code := ( is u:Unary do ( if u.Operator.word == CommaW then Code(sequenceCode(makeCodeSequence(e, CommaW), pos)) else if u.Operator.word == SemicolonW then Code(semiCode( makeCodeSequence(e, SemicolonW), pos)) - else Code(unaryCode(u.Operator.entry.unary, convert(u.rhs), pos))) - is u:Postfix do Code(unaryCode(u.Operator.entry.postfix, convert(u.lhs), pos)) + else ( + f:=u.Operator.entry.unary; + if f==dummyUnaryFun then + Code(binaryCode(unarymethod1,convert(u.rhs), globalSymbolClosureCode(u.Operator.entry, dummyPosition),pos)) + else + Code(unaryCode(f, convert(u.rhs), pos)) + )) + is u:Postfix do ( + f:=u.Operator.entry.postfix; + if f==dummyPostfixFun then + Code(binaryCode(unarymethod1,convert(u.lhs), globalSymbolClosureCode(u.Operator.entry, dummyPosition),pos)) + else + Code(unaryCode(f, convert(u.lhs), pos)) + ) is q:Quote do ( token := q.rhs; sym := token.entry; diff --git a/M2/Macaulay2/d/evaluate.d b/M2/Macaulay2/d/evaluate.d index e7f5009d9db..f3bfaf394f8 100644 --- a/M2/Macaulay2/d/evaluate.d +++ b/M2/Macaulay2/d/evaluate.d @@ -1125,6 +1125,11 @@ export binarymethodCode(lhs:Code,rhs:Code,methodkey:Code):Expr := ( s:globalSymbolClosureCode do binarymethod(lhs,rhs,SymbolClosure(globalFrame,s.symbol)) else nullE ); +export unarymethodCode(rhs:Code,methodkey:Code):Expr := ( + when methodkey is + s:globalSymbolClosureCode do unarymethod(rhs,SymbolClosure(globalFrame,s.symbol)) + else nullE +); ----------------------------------------------------------------------------- @@ -2118,6 +2123,7 @@ nullCoalescion(lhs:Code,rhs:Code):Expr := ( setup(QuestionQuestionS, nullify, nullCoalescion); binarymethod1=binarymethodCode; +unarymethod1=unarymethodCode; -- Local Variables: -- compile-command: "echo \"make: Entering directory \\`$M2BUILDDIR/Macaulay2/d'\" && make -C $M2BUILDDIR/Macaulay2/d evaluate.o " From 45f7ca9eed7f1db3cb16c68f2848e6d2cd31f10e Mon Sep 17 00:00:00 2001 From: pzinn Date: Thu, 28 Nov 2024 23:17:54 +1100 Subject: [PATCH 03/14] implement user-defined prefix, postfix, binary keywords --- M2/Macaulay2/d/actors5.d | 34 +++++++++++++++++++++++++++++----- M2/Macaulay2/m2/exports.m2 | 2 ++ M2/Macaulay2/m2/methods.m2 | 16 ++++++++++++++++ M2/Macaulay2/m2/set.m2 | 3 --- 4 files changed, 47 insertions(+), 8 deletions(-) diff --git a/M2/Macaulay2/d/actors5.d b/M2/Macaulay2/d/actors5.d index 0f100b9a6c4..eb1f4940bb2 100644 --- a/M2/Macaulay2/d/actors5.d +++ b/M2/Macaulay2/d/actors5.d @@ -15,13 +15,37 @@ getParsing(e:Expr):Expr := ( setupfun("getParsing",getParsing); export makeKeywordFun(e:Expr):Expr := ( - when e - is s:stringCell do ( - Expr(makeKeyword(binaryleft(s.v))) -- TODO check whether install is really needed (for mathematical symbols as opposed to words) + when e + is seq:Sequence do ( + when seq.0 + is s:stringCell do + when seq.1 + is p:ZZcell do + when seq.2 + is b1:Boolean do + when seq.3 + is b2:Boolean do ( + u:=errorunary; + t:=errorbinary; + prec:=toInt(p); + uprec:=nopr; + bprec:=nopr; + if b1.v || b2.v then ( + if b1.v then (t=binaryop; bprec=prec); + if b2.v then (u=unaryop; uprec=prec); + ) else t=postfixop; + w:=makeUniqueWord(s.v, parseinfo(prec,bprec,uprec,parsefuns(u,t))); + install(s.v,w); -- TODO check whether install is really needed (for mathematical symbols as opposed to words) + Expr(makeKeyword(w)) + ) + else nullE + else nullE + else nullE + else nullE -- TODO error (but anyway won't be called directly) ) else nullE -- TODO error (but anyway won't be called directly) - ); -setupfun("makeKeyword",makeKeywordFun); + ); +setupfun("makeKeyword",makeKeywordFun).Protected = false; -- will be overloaded in m2/methods.m2 -- doublePointerfun(lhs:Code,rhs:Code):Expr := binarymethod(lhs,rhs,DoubleArrowS); optionFun(lhs:Code,rhs:Code):Expr := ( diff --git a/M2/Macaulay2/m2/exports.m2 b/M2/Macaulay2/m2/exports.m2 index a1dd5453ffd..cff04fede4c 100644 --- a/M2/Macaulay2/m2/exports.m2 +++ b/M2/Macaulay2/m2/exports.m2 @@ -328,6 +328,7 @@ export { "Position", "Postfix", "Power", + "Precedence", "Precision", "Prefix", "PrimaryTag", @@ -403,6 +404,7 @@ export { "Superscript", "Symbol", "SymbolBody", + "Syntax", "Syzygies", "SyzygyLimit", "SyzygyMatrix", diff --git a/M2/Macaulay2/m2/methods.m2 b/M2/Macaulay2/m2/methods.m2 index d1b0f21f983..d4efbac5a2a 100644 --- a/M2/Macaulay2/m2/methods.m2 +++ b/M2/Macaulay2/m2/methods.m2 @@ -732,6 +732,22 @@ registerFinalizer' = registerFinalizer registerFinalizer = method() registerFinalizer(Thing, String) := registerFinalizer' +-- move to a new file keywords.m2? +protect Binary +protect Prefix +protect Postfix +protect Precedence +protect Syntax +makeKeyword'=makeKeyword +makeKeyword=method(TypicalValue => Keyword, Options => { Precedence => symbol *, Syntax => Binary }) +makeKeyword String := o -> s -> ( + pr:=if instance(o.Precedence,Symbol) then (getParsing o.Precedence)#0 else o.Precedence; + makeKeyword'(s, + pr, + o.Syntax === Binary or (class o.Syntax === List and isMember(Binary,o.Syntax)), + o.Syntax === Prefix or (class o.Syntax === List and isMember(Prefix,o.Syntax)) + )) + -- Local Variables: -- compile-command: "make -C $M2BUILDDIR/Macaulay2/m2 " -- End: diff --git a/M2/Macaulay2/m2/set.m2 b/M2/Macaulay2/m2/set.m2 index 39e71c05e88..c1917d4cc55 100644 --- a/M2/Macaulay2/m2/set.m2 +++ b/M2/Macaulay2/m2/set.m2 @@ -183,9 +183,6 @@ fixedOperators = unique toList fixedOperators allOperators = unique toList allOperators protect Flexible -protect Binary -protect Prefix -protect Postfix operatorAttributes = new MutableHashTable from apply(allOperators, op -> op => new MutableHashTable) scan(( (binaryOperators,Binary), From 5aac89c8811eff93d6a177b9f24319280cd4cdd7 Mon Sep 17 00:00:00 2001 From: pzinn Date: Fri, 29 Nov 2024 08:57:18 +1100 Subject: [PATCH 04/14] fix augmented ops --- M2/Macaulay2/d/evaluate.d | 49 +++++++++++++++++++-------------------- 1 file changed, 24 insertions(+), 25 deletions(-) diff --git a/M2/Macaulay2/d/evaluate.d b/M2/Macaulay2/d/evaluate.d index f3bfaf394f8..6639abaf1fd 100644 --- a/M2/Macaulay2/d/evaluate.d +++ b/M2/Macaulay2/d/evaluate.d @@ -1274,34 +1274,33 @@ augmentedAssignmentFun(x:augmentedAssignmentCode):Expr := ( else return r) else return r); -- if not, use default behavior + r:=nullE; + f:=s.binary; if f==dummyBinaryFun then + r=binarymethod(Code(left),x.rhs,SymbolClosure(globalFrame,s)) + else + r=f(Code(left),x.rhs); + when r is e:Error do Expr(e) else ( when x.lhs - is y:globalMemoryReferenceCode do ( - r := s.binary(Code(left), x.rhs); - when r is e:Error do Expr(e) - else globalAssignment(y.frameindex, x.info, r)) - is y:localMemoryReferenceCode do ( - r := s.binary(Code(left), x.rhs); - when r is e:Error do Expr(e) - else localAssignment(y.nestingDepth, y.frameindex, r)) - is y:threadMemoryReferenceCode do ( - r := s.binary(Code(left), x.rhs); - when r is e:Error do Expr(e) - else globalAssignment(y.frameindex, x.info, r)) + is y:globalMemoryReferenceCode do globalAssignment(y.frameindex, x.info, r) + is y:localMemoryReferenceCode do localAssignment(y.nestingDepth, y.frameindex, r) + is y:threadMemoryReferenceCode do globalAssignment(y.frameindex, x.info, r) is y:binaryCode do ( - r := Code(binaryCode(s.binary, Code(left), x.rhs, dummyPosition)); - if y.f == DotS.symbol.binary || y.f == SharpS.symbol.binary - then AssignElemFun(y.lhs, y.rhs, r) - else InstallValueFun(CodeSequence( - convertGlobalOperator(x.info), y.lhs, y.rhs, r))) - is y:adjacentCode do ( - r := Code(binaryCode(s.binary, Code(left), x.rhs, dummyPosition)); - InstallValueFun(CodeSequence( - convertGlobalOperator(AdjacentS.symbol), y.lhs, y.rhs, r))) - is y:unaryCode do ( - r := Code(binaryCode(s.binary, Code(left), x.rhs, dummyPosition)); - UnaryInstallValueFun(convertGlobalOperator(x.info), y.rhs, r)) + if y.f == DotS.symbol.binary || y.f == SharpS.symbol.binary + then AssignElemFun(y.lhs, y.rhs, Code(evaluatedCode(r,dummyPosition))) + else if y.f == unarymethodCode then UnaryInstallValueFun(convertGlobalOperator(x.info), y.lhs, Code(evaluatedCode(r,dummyPosition))) -- y.rhs redundant + else InstallValueFun(CodeSequence( + convertGlobalOperator(x.info), y.lhs, y.rhs, Code(evaluatedCode(r,dummyPosition))))) -- y.f redundant + is y:ternaryCode do ( -- TODO check binarymethodCode? + InstallValueFun(CodeSequence( + convertGlobalOperator(x.info), y.arg1, y.arg2, Code(evaluatedCode(r,dummyPosition))))) -- y.arg3 redundant -- combine with previous case? + is y:adjacentCode do ( + InstallValueFun(CodeSequence( + convertGlobalOperator(AdjacentS.symbol), y.lhs, y.rhs, Code(evaluatedCode(r,dummyPosition))))) + is y:unaryCode do ( + UnaryInstallValueFun(convertGlobalOperator(x.info), y.rhs, Code(evaluatedCode(r,dummyPosition)))) else buildErrorPacket( - "augmented assignment not implemented for this code"))); + "augmented assignment not implemented for this code") + ))); ----------------------------------------------------------------------------- steppingFurther(c:Code):bool := steppingFlag && ( From 47208670913f8859760f248be8673505e8003386 Mon Sep 17 00:00:00 2001 From: pzinn Date: Fri, 29 Nov 2024 09:18:03 +1100 Subject: [PATCH 05/14] minor keyword/symbol fixes --- M2/Macaulay2/d/actors5.d | 7 ++++++- M2/Macaulay2/d/binding.d | 4 ++-- M2/Macaulay2/m2/expressions.m2 | 13 ++++--------- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/M2/Macaulay2/d/actors5.d b/M2/Macaulay2/d/actors5.d index eb1f4940bb2..af6f7e16c40 100644 --- a/M2/Macaulay2/d/actors5.d +++ b/M2/Macaulay2/d/actors5.d @@ -1994,7 +1994,12 @@ functionBody(e:Expr):Expr := ( ); setupfun("functionBody",functionBody); -symbolBody(e:Expr):Expr := when e is s:SymbolClosure do Expr(SymbolBody(s.symbol)) else WrongArg("a symbol"); +symbolBody(e:Expr):Expr := ( + when e + is s:SymbolClosure do Expr(SymbolBody(s.symbol)) + is s:SpecialExpr do symbolBody(s.e) + else WrongArg("a symbol") + ); setupfun("symbolBody",symbolBody); dumpNodes(e:Expr):Expr := (dumpNodes(); nullE); diff --git a/M2/Macaulay2/d/binding.d b/M2/Macaulay2/d/binding.d index 0bab20b7ad1..765eee48e0d 100644 --- a/M2/Macaulay2/d/binding.d +++ b/M2/Macaulay2/d/binding.d @@ -157,7 +157,7 @@ unaryword(s:string) :Word := makeUniqueWord(s, parseinfo(prec,nopr postfix(s:string) :Word := install(s,makeUniqueWord(s, parseinfo(prec,nopr ,nopr,parsefuns(errorunary,postfixop)))); unarybinaryleft(s:string) :Word := install(s,makeUniqueWord(s, parseinfo(prec,prec ,prec,parsefuns(unaryop ,binaryop)))); unarybinaryright(s:string) :Word := install(s,makeUniqueWord(s, parseinfo(prec,prec-1,prec,parsefuns(unaryop ,binaryop)))); -export binaryleft(s:string) :Word := install(s,makeUniqueWord(s, parseinfo(prec,prec ,nopr,parsefuns(errorunary,binaryop)))); +binaryleft(s:string) :Word := install(s,makeUniqueWord(s, parseinfo(prec,prec ,nopr,parsefuns(errorunary,binaryop)))); nright(s:string) :Word := install(s,makeUniqueWord(s, parseinfo(prec,prec-1,nopr,parsefuns(errorunary,nbinaryop)))); nleftword(s:string) :Word := makeUniqueWord(s, parseinfo(prec,prec ,nopr,parsefuns(errorunary,nbinaryop))); nunarybinaryleft(s:string) :Word := install(s,makeUniqueWord(s, parseinfo(prec,prec ,prec,parsefuns(nnunaryop ,nbinaryop)))); @@ -190,7 +190,7 @@ special(s:string,f:function(Token,TokenFile,int,bool):ParseTree,lprec:int,rprec: -- created below are all in the global dictionary. -- new operators must be: --- set up as an "actor" with "setup()" +-- set up as an "actor" with "setup()" -- or not TODO explain -- added to the export list in ../m2/exports.m2 -- added to the table binaryOperatorFunctions in ../m2/expressions.m2 -- added to the list of operators in the documentation node "operators" in ../packages/Macaulay2Doc/ov_language.m2 diff --git a/M2/Macaulay2/m2/expressions.m2 b/M2/Macaulay2/m2/expressions.m2 index 1ad64e8df52..d5acb03034e 100644 --- a/M2/Macaulay2/m2/expressions.m2 +++ b/M2/Macaulay2/m2/expressions.m2 @@ -1250,15 +1250,10 @@ net Set := net @@ expression texMath Set := texMath @@ expression -- shortening expressions -Dots = new Type of Symbol -cdots=new Dots from symbol cdots -ddots=new Dots from symbol ddots -vdots=new Dots from symbol vdots -ldots=new Dots from symbol ldots -texMath Dots := x -> "\\" | simpleToString x -- note that \vdots has bad spacing in ordinary LaTeX -toString Dots := x -> "..." -net Dots := x -> if x === vdots then "."||"."||"." else if x === ddots then ". "||" . "||" ." else "..." - +cdots=⋯:=symbol ⋯ +ddots=⋱:=symbol ⋱ +vdots=⋮:=symbol ⋮ +ldots=…:=symbol … -- used e.g. in chaincomplexes.m2 shortLength := 8 shortStringLength := 3*shortLength From f34fe1ceafe3774850ad4f20a0667befdda7cca0 Mon Sep 17 00:00:00 2001 From: pzinn Date: Fri, 29 Nov 2024 12:56:29 +1100 Subject: [PATCH 06/14] clean up binding.d --- M2/Macaulay2/d/binding.d | 63 +++++++--------------------------------- 1 file changed, 10 insertions(+), 53 deletions(-) diff --git a/M2/Macaulay2/d/binding.d b/M2/Macaulay2/d/binding.d index 765eee48e0d..2b708cd64e2 100644 --- a/M2/Macaulay2/d/binding.d +++ b/M2/Macaulay2/d/binding.d @@ -643,21 +643,6 @@ bindParenParmList(e:ParseTree,dictionary:Dictionary,desc:functionDescription):vo ) is p:EmptyParentheses do nothing else makeErrorTree(e,"expected parenthesized argument list or symbol")); -opHasBinaryMethod(o:Symbol):bool := ( - return true; -- TEMP - foreach s in opsWithBinaryMethod do if s.symbol == o then return true; - return false; - ); -opHasUnaryMethod(o:Symbol):bool := ( - return true; -- TEMP - foreach s in opsWithUnaryMethod do if s.symbol == o then return true; - return false; - ); -opHasPostfixMethod(o:Symbol):bool := ( - return true; -- TEMP - foreach s in opsWithPostfixMethod do if s.symbol == o then return true; - return false; - ); bindTokenLocally(t:Token,dictionary:Dictionary):void := ( lookupCountIncrement = 0; r := lookup(t.word,dictionary); @@ -718,54 +703,26 @@ bindassignment(assn:Binary,dictionary:Dictionary,colon:bool):void := ( bindop(unary.Operator,dictionary); bind(unary.rhs,dictionary); bind(body,dictionary); - if colon - then ( - if ! opHasUnaryMethod(unary.Operator.entry) - then makeErrorTree(assn.Operator, "can't assign a method for this unary operator"); - ) - else ( - if ! opHasUnaryMethod(unary.Operator.entry) - then makeErrorTree(assn.Operator, "can't assign a value for this unary operator") - ) ) is unary:Postfix do ( bind(unary.lhs,dictionary); bindop(unary.Operator,dictionary); bind(body,dictionary); - if colon - then ( - if ! opHasPostfixMethod(unary.Operator.entry) - then makeErrorTree(assn.Operator, "can't assign a method for this postfix operator"); - ) - else ( - if ! opHasPostfixMethod(unary.Operator.entry) - then makeErrorTree(assn.Operator, "can't assign a value for this postfix operator") - ) ) is binary:Binary do ( bind(binary.lhs,dictionary); bindop(binary.Operator,dictionary); - bind(binary.rhs, if binary.Operator.word == DotS.symbol.word then globalDictionary else dictionary ); + bind(binary.rhs, if binary.Operator.word == DotS.symbol.word then globalDictionary else dictionary); bind(body,dictionary); - if colon then ( - if ! opHasBinaryMethod(binary.Operator.entry) - then makeErrorTree( assn.Operator, "can't assign a method for this binary operator"); - ) - else ( - if !(binary.Operator.word == DotS.symbol.word - || - binary.Operator.word == SharpS.symbol.word - || - opHasBinaryMethod(binary.Operator.entry)) - then makeErrorTree( assn.Operator, "can't assign a value for this binary operator"); - if binary.Operator.word == DotS.symbol.word then ( - when binary.rhs is t:Token do ( - if t.word.typecode != TCid - then makeErrorTree(assn.Operator, "expected a symbol to right of '.'"); - ) - else makeErrorTree(assn.Operator, "expected a symbol to right of '.'"); - ); - ) + if colon && (binary.Operator.word == DotS.symbol.word + || + binary.Operator.word == SharpS.symbol.word + ) then makeErrorTree( assn.Operator, "can't assign a method for this binary operator"); + if binary.Operator.word == DotS.symbol.word then ( + when binary.rhs is t:Token do return + else nothing; + makeErrorTree(assn.Operator, "expected a symbol to right of '.'"); + ); ) is n:New do ( if colon then ( From 288c88277ae840e2a911606ef46bdeef5d67d990 Mon Sep 17 00:00:00 2001 From: pzinn Date: Fri, 29 Nov 2024 21:37:35 +1100 Subject: [PATCH 07/14] fix pseudocode/disassemble for keywords --- M2/Macaulay2/d/debugging.dd | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/M2/Macaulay2/d/debugging.dd b/M2/Macaulay2/d/debugging.dd index fc93b42b648..9b587590e09 100644 --- a/M2/Macaulay2/d/debugging.dd +++ b/M2/Macaulay2/d/debugging.dd @@ -2,6 +2,7 @@ use tokens; use common; use util; use hashtables; +use convertr; export tostring(c:Code):string := ( when c @@ -46,8 +47,16 @@ export tostring(c:Code):string := ( is x:catchCode do concatenate(array(string)("(catch ", tostring(x.code), ")")) -- is x:unaryCode do concatenate(array(string)("(1-OP ", getUnopName(x.f).word.name, " ", tostring(x.rhs), ")")) - is x:binaryCode do concatenate(array(string)("(2-OP ", getBinopName(x.f).word.name, " ", tostring(x.lhs), " ", tostring(x.rhs), ")")) - is x:ternaryCode do concatenate(array(string)("(3-OP ", getTernopName(x.f).word.name, " ", tostring(x.arg1), " ", tostring(x.arg2), " ", tostring(x.arg3), ")")) + is x:binaryCode do if x.f == unarymethod1 then ( + when x.rhs is s:globalSymbolClosureCode do concatenate(array(string)("(1-OP ", s.symbol.word.name, " ", tostring(x.rhs), ")")) + else "" + ) + else concatenate(array(string)("(2-OP ", getBinopName(x.f).word.name, " ", tostring(x.lhs), " ", tostring(x.rhs), ")")) + is x:ternaryCode do if x.f == binarymethod1 then ( + when x.arg3 is s:globalSymbolClosureCode do concatenate(array(string)("(2-OP ", s.symbol.word.name, " ", tostring(x.arg1), " ", tostring(x.arg2), ")")) + else "" + ) + else concatenate(array(string)("(3-OP ", getTernopName(x.f).word.name, " ", tostring(x.arg1), " ", tostring(x.arg2), " ", tostring(x.arg3), ")")) is x:multaryCode do concatenate(array(string)("(OP ", getMultopName(x.f).word.name, " ", between(" ", new array(string) len length(x.args) do foreach c in x.args do provide tostring(c)), ")")) is x:adjacentCode do concatenate(array(string)("(adjacent ", tostring(x.lhs), " ", tostring(x.rhs), ")")) @@ -121,8 +130,16 @@ export toList(c:Code):Expr := ( is x:catchCode do list(toExpr("catch"), seq(toExpr(x.code))) -- is x:unaryCode do list(toExpr("1-OP"), Expr(SymbolBody(getUnopName(x.f))), seq(toExpr(x.rhs))) - is x:binaryCode do list(toExpr("2-OP"), Expr(SymbolBody(getBinopName(x.f))), seq(toExpr(x.lhs), toExpr(x.rhs))) - is x:ternaryCode do list(toExpr("3-OP"), Expr(SymbolBody(getTernopName(x.f))), seq(toExpr(x.arg1), toExpr(x.arg2), toExpr(x.arg3))) + is x:binaryCode do if x.f == unarymethod1 then ( + when x.rhs is s:globalSymbolClosureCode do list(toExpr("1-OP"), Expr(SymbolBody(s.symbol)), seq(toExpr(x.lhs))) + else nullE + ) + else list(toExpr("2-OP"), Expr(SymbolBody(getBinopName(x.f))), seq(toExpr(x.lhs), toExpr(x.rhs))) + is x:ternaryCode do if x.f == binarymethod1 then ( + when x.arg3 is s:globalSymbolClosureCode do list(toExpr("2-OP"), Expr(SymbolBody(s.symbol)), seq(toExpr(x.arg1), toExpr(x.arg2))) + else nullE + ) + else list(toExpr("3X-OP"), Expr(SymbolBody(getTernopName(x.f))), seq(toExpr(x.arg1), toExpr(x.arg2), toExpr(x.arg3))) is x:multaryCode do list(toExpr("OP"), Expr(SymbolBody(getMultopName(x.f))), Expr(new Sequence len length(x.args) do foreach c in x.args do provide toExpr(c))) is x:adjacentCode do list(toExpr("adjacent"), seq(toExpr(x.lhs), toExpr(x.rhs))) From 699cd909d72ed2bdf661ac4a6d720a35a9d11e7c Mon Sep 17 00:00:00 2001 From: pzinn Date: Fri, 29 Nov 2024 23:05:22 +1100 Subject: [PATCH 08/14] prevent "new Keyword" --- M2/Macaulay2/d/actors2.dd | 2 ++ 1 file changed, 2 insertions(+) diff --git a/M2/Macaulay2/d/actors2.dd b/M2/Macaulay2/d/actors2.dd index 1f8b7de3d3d..4be24ac4b5d 100644 --- a/M2/Macaulay2/d/actors2.dd +++ b/M2/Macaulay2/d/actors2.dd @@ -162,6 +162,7 @@ wrongTarget():Expr := buildErrorPacket("'new' expected a type of list or hash ta newClassParent(e:Expr,classs:HashTable,parent:HashTable,returned:bool):Expr := ( -- same as below, but parent specified + if classs == keywordClass then return buildErrorPacket("invalid new Keyword (use makeKeyword)"); basicType := basictype(classs); when e is Error do e @@ -202,6 +203,7 @@ newClassParent(e:Expr,classs:HashTable,parent:HashTable,returned:bool):Expr := ( else Expr(SpecialExpr(classs,e)))); newClass(e:Expr,classs:HashTable,returned:bool):Expr := ( + if classs == keywordClass then return buildErrorPacket("invalid new Keyword (use makeKeyword)"); -- same as above, but no parent specified, so leave what s provided alone when e is Error do e From 9d484926b0b83c727003ff5f4f2879a20195096a Mon Sep 17 00:00:00 2001 From: pzinn Date: Sat, 30 Nov 2024 11:59:05 +1100 Subject: [PATCH 09/14] makeKeyword checks and errors --- M2/Macaulay2/d/actors5.d | 41 +++++++++++++++++++++----------------- M2/Macaulay2/m2/methods.m2 | 4 +++- 2 files changed, 26 insertions(+), 19 deletions(-) diff --git a/M2/Macaulay2/d/actors5.d b/M2/Macaulay2/d/actors5.d index af6f7e16c40..46f1ff87a6e 100644 --- a/M2/Macaulay2/d/actors5.d +++ b/M2/Macaulay2/d/actors5.d @@ -16,7 +16,10 @@ setupfun("getParsing",getParsing); export makeKeywordFun(e:Expr):Expr := ( when e - is seq:Sequence do ( + is seq:Sequence do + if length(seq) != 4 + then WrongNumArgs(4) + else ( when seq.0 is s:stringCell do when seq.1 @@ -25,25 +28,27 @@ export makeKeywordFun(e:Expr):Expr := ( is b1:Boolean do when seq.3 is b2:Boolean do ( - u:=errorunary; - t:=errorbinary; - prec:=toInt(p); - uprec:=nopr; - bprec:=nopr; - if b1.v || b2.v then ( - if b1.v then (t=binaryop; bprec=prec); - if b2.v then (u=unaryop; uprec=prec); - ) else t=postfixop; - w:=makeUniqueWord(s.v, parseinfo(prec,bprec,uprec,parsefuns(u,t))); - install(s.v,w); -- TODO check whether install is really needed (for mathematical symbols as opposed to words) - Expr(makeKeyword(w)) + u:=errorunary; + t:=errorbinary; + prec:=toInt(p); + uprec:=nopr; + bprec:=nopr; + if b1.v || b2.v then ( + if b1.v then (t=binaryop; bprec=prec); + if b2.v then (u=unaryop; uprec=prec); + ) else t=postfixop; + w:=makeUniqueWord(s.v, parseinfo(prec,bprec,uprec,parsefuns(u,t))); + when globalLookup(w) is x:Symbol do buildErrorPacket("symbol already in use") + else ( + install(s.v,w); -- TODO check whether install is really needed (for mathematical symbols as opposed to words) + Expr(makeKeyword(w))) ) - else nullE - else nullE - else nullE - else nullE -- TODO error (but anyway won't be called directly) + else WrongArg(4,"a boolean") + else WrongArg(3,"a boolean") + else WrongArg(2,"an integer") + else WrongArg(1,"a string") ) - else nullE -- TODO error (but anyway won't be called directly) + else WrongNumArgs(4) ); setupfun("makeKeyword",makeKeywordFun).Protected = false; -- will be overloaded in m2/methods.m2 diff --git a/M2/Macaulay2/m2/methods.m2 b/M2/Macaulay2/m2/methods.m2 index d4efbac5a2a..cb24367dda4 100644 --- a/M2/Macaulay2/m2/methods.m2 +++ b/M2/Macaulay2/m2/methods.m2 @@ -740,8 +740,10 @@ protect Precedence protect Syntax makeKeyword'=makeKeyword makeKeyword=method(TypicalValue => Keyword, Options => { Precedence => symbol *, Syntax => Binary }) +syntaxOptions:=set {Binary,Prefix,Postfix,{Binary,Prefix},{Prefix,Binary}} makeKeyword String := o -> s -> ( - pr:=if instance(o.Precedence,Symbol) then (getParsing o.Precedence)#0 else o.Precedence; + pr:=if instance(o.Precedence,Symbol) then (getParsing o.Precedence)#0 else if instance(o.Precedence,ZZ) then o.Precedence else error "incorrect Symbol option"; + if not isMember(o.Syntax,syntaxOptions) then error "incorrect Syntax option"; makeKeyword'(s, pr, o.Syntax === Binary or (class o.Syntax === List and isMember(Binary,o.Syntax)), From d14dca3184592fdf852123873b894a6d40701c00 Mon Sep 17 00:00:00 2001 From: pzinn Date: Sat, 30 Nov 2024 13:22:12 +1100 Subject: [PATCH 10/14] fix getSymbol bugs --- M2/Macaulay2/d/actors5.d | 6 ++++-- M2/Macaulay2/d/ctype.d | 1 + M2/Macaulay2/m2/methods.m2 | 2 +- M2/Macaulay2/packages/Macaulay2Doc/repl.m2 | 2 +- 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/M2/Macaulay2/d/actors5.d b/M2/Macaulay2/d/actors5.d index 46f1ff87a6e..7d16e22c4f0 100644 --- a/M2/Macaulay2/d/actors5.d +++ b/M2/Macaulay2/d/actors5.d @@ -1505,8 +1505,10 @@ createSymbol(w:Word, d:Dictionary, s:string):Expr := ( getglobalsym(d:Dictionary,s:string):Expr := ( w := makeUniqueWord(s,parseWORD); - when lookup(w,d.symboltable) is x:Symbol do Expr(SymbolClosure(globalFrame,x)) - is null do createSymbol(w, d, s)); + when lookup(w,d.symboltable) + is x:Symbol do Expr(SymbolClosure(globalFrame,x)) + is null do if w.parse != parseWORD then buildErrorPacket("symbol is a keyword") else createSymbol(w, d, s) + ); getglobalsym(s:string):Expr := ( w := makeUniqueWord(s,parseWORD); diff --git a/M2/Macaulay2/d/ctype.d b/M2/Macaulay2/d/ctype.d index c08b28f1d1b..308b88a1bb3 100644 --- a/M2/Macaulay2/d/ctype.d +++ b/M2/Macaulay2/d/ctype.d @@ -67,6 +67,7 @@ ismathoperator(c1:char, c2:char):bool := ( ismathoperator((int(uchar(c1)) << 8) | int(uchar(c2)))); export isvalidsymbol(s:string):bool := ( + if length(s)==0 then return false; -- duh if !isalpha(s.0) then return false; if ismathoperator(s.0, s.1) && length(s) == utf8charlength(s.0) then return true; diff --git a/M2/Macaulay2/m2/methods.m2 b/M2/Macaulay2/m2/methods.m2 index cb24367dda4..545e8558a5b 100644 --- a/M2/Macaulay2/m2/methods.m2 +++ b/M2/Macaulay2/m2/methods.m2 @@ -439,7 +439,7 @@ flatten VisibleList := VisibleList => oldflatten ----------------------------------------------------------------------------- dictionary = method() -dictionary Keyword := s -> Core.Dictionary +-- dictionary Keyword := s -> Core.Dictionary -- unnecessary and makes debugging harder dictionary Symbol := s -> ( -- eventually every symbol will know what dictionary it's in, perhaps n := toString s; scan(dictionaryPath, d -> if d#?n and d#n === s then break d)) diff --git a/M2/Macaulay2/packages/Macaulay2Doc/repl.m2 b/M2/Macaulay2/packages/Macaulay2Doc/repl.m2 index 0f59ca0a610..ada4d06004d 100644 --- a/M2/Macaulay2/packages/Macaulay2Doc/repl.m2 +++ b/M2/Macaulay2/packages/Macaulay2Doc/repl.m2 @@ -784,7 +784,7 @@ document { } document { - Key => {dictionary,(dictionary, Keyword),(dictionary, Symbol),(dictionary, Thing)}, + Key => {dictionary,(dictionary, Symbol),(dictionary, Thing)}, Headline => "determine the dictionary to which a symbol belongs", Usage => "dictionary x", Inputs => { From 5fe540308b36b1dfaa33f29d3ccc43709f84169d Mon Sep 17 00:00:00 2001 From: pzinn Date: Sat, 30 Nov 2024 22:03:53 +1100 Subject: [PATCH 11/14] add isvalidkeyword --- M2/Macaulay2/d/actors5.d | 8 +++++--- M2/Macaulay2/d/ctype.d | 19 +++++++++++++++++++ M2/Macaulay2/d/lex.d | 3 ++- 3 files changed, 26 insertions(+), 4 deletions(-) diff --git a/M2/Macaulay2/d/actors5.d b/M2/Macaulay2/d/actors5.d index 7d16e22c4f0..ef9148265c4 100644 --- a/M2/Macaulay2/d/actors5.d +++ b/M2/Macaulay2/d/actors5.d @@ -28,6 +28,8 @@ export makeKeywordFun(e:Expr):Expr := ( is b1:Boolean do when seq.3 is b2:Boolean do ( + validSymbol:=isvalidsymbol(s.v) && length(s.v)>1; + if !validSymbol && !isvalidkeyword(s.v) then buildErrorPacket("invalid keyword") else ( u:=errorunary; t:=errorbinary; prec:=toInt(p); @@ -40,9 +42,9 @@ export makeKeywordFun(e:Expr):Expr := ( w:=makeUniqueWord(s.v, parseinfo(prec,bprec,uprec,parsefuns(u,t))); when globalLookup(w) is x:Symbol do buildErrorPacket("symbol already in use") else ( - install(s.v,w); -- TODO check whether install is really needed (for mathematical symbols as opposed to words) + if !validSymbol then install(s.v,w); -- install only needed for nonstandard symbols Expr(makeKeyword(w))) - ) + )) else WrongArg(4,"a boolean") else WrongArg(3,"a boolean") else WrongArg(2,"an integer") @@ -1507,7 +1509,7 @@ getglobalsym(d:Dictionary,s:string):Expr := ( w := makeUniqueWord(s,parseWORD); when lookup(w,d.symboltable) is x:Symbol do Expr(SymbolClosure(globalFrame,x)) - is null do if w.parse != parseWORD then buildErrorPacket("symbol is a keyword") else createSymbol(w, d, s) + is null do if w.parse != parseWORD then buildErrorPacket("symbol "+s+" is a keyword") else createSymbol(w, d, s) ); getglobalsym(s:string):Expr := ( diff --git a/M2/Macaulay2/d/ctype.d b/M2/Macaulay2/d/ctype.d index 308b88a1bb3..1e6d3907856 100644 --- a/M2/Macaulay2/d/ctype.d +++ b/M2/Macaulay2/d/ctype.d @@ -12,9 +12,11 @@ CTRL := 64; ALNUMEXTRA := 128; HEX := 256; BINARY := 512; +SPECIAL := 1024; SPACE := WHITE | NEWLINE; ALPHA := UPPER | LOWER; ALNUM := ALPHA | DIGIT | ALNUMEXTRA; +NOTKW := ALNUM | SPACE | QUOTE | SPECIAL; foreach c in "ABCDEFGHIJKLMNOPQRSTUVWXYZ" do setchartype(c,UPPER); foreach c in "abcdefghijklmnopqrstuvwxyz" do setchartype(c,LOWER); @@ -24,6 +26,7 @@ foreach c in "01" do setchartype(c,BINARY); foreach c in " \t\r" do setchartype(c,WHITE); foreach c in "\n" do setchartype(c,NEWLINE); foreach c in "$'" do setchartype(c,ALNUMEXTRA); +foreach c in ".#;," do setchartype(c,SPECIAL); for c from 128 to 255 do setchartype(char(c),ALPHA); setchartype('\"',QUOTE); @@ -40,6 +43,7 @@ export iswhite (c:int ):bool := (chartype(c) & WHITE ) != 0; export isspace (c:int ):bool := (chartype(c) & SPACE ) != 0; export isnewline (c:int ):bool := (chartype(c) & NEWLINE ) != 0; export isquote (c:int ):bool := (chartype(c) & QUOTE ) != 0; +export isnotkw (c:int ):bool := (chartype(c) & NOTKW ) != 0; export isdigit (c:char):bool := (chartype(c) & DIGIT ) != 0; export ishex (c:char):bool := (chartype(c) & HEX ) != 0; @@ -50,6 +54,7 @@ export iswhite (c:char):bool := (chartype(c) & WHITE ) != 0; export isspace (c:char):bool := (chartype(c) & SPACE ) != 0; export isnewline (c:char):bool := (chartype(c) & NEWLINE ) != 0; export isquote (c:char):bool := (chartype(c) & QUOTE ) != 0; +export isnotkw (c:char):bool := (chartype(c) & NOTKW ) != 0; -- c = two bytes concatenated export ismathoperator(c:int):bool := ( @@ -76,6 +81,20 @@ export isvalidsymbol(s:string):bool := ( then return false); true); +export isvalidkeyword(s:string):bool := ( + if length(s)==0 then return false; + for i from 0 to length(s) - 1 do ( + if isnotkw(s.i) then return false; + if i Date: Sat, 30 Nov 2024 22:16:39 +1100 Subject: [PATCH 12/14] removed unicode keywords, added tests --- M2/Macaulay2/d/binding.d | 9 +-------- M2/Macaulay2/m2/exports.m2 | 3 --- M2/Macaulay2/m2/latex.m2 | 2 +- M2/Macaulay2/tests/normal/symbols.m2 | 3 ++- M2/Macaulay2/tests/normal/unicode.m2 | 1 + 5 files changed, 5 insertions(+), 13 deletions(-) diff --git a/M2/Macaulay2/d/binding.d b/M2/Macaulay2/d/binding.d index 2b708cd64e2..18236a2b1ac 100644 --- a/M2/Macaulay2/d/binding.d +++ b/M2/Macaulay2/d/binding.d @@ -285,12 +285,8 @@ bumpPrecedence(); export MinusS := makeKeyword(unarybinaryleft("-")); -- also binary export PlusS := makeKeyword(unarybinaryleft("+")); -- also binary export PlusPlusS := makeKeyword(binaryleft("++")); -bumpPrecedence(); - export InterpunctS := makeKeyword(binaryleft("·")); bumpPrecedence(); export StarStarS := makeKeyword(binaryleft("**")); - export BoxTimesS := makeKeyword(binaryleft("⊠")); - export ShuffleProductS := makeKeyword(binaryleft("⧢")); bumpPrecedence(); precBracket := prec; export leftbracket := parens("[","]",precBracket, precRightParen, precRightParen); @@ -515,10 +511,7 @@ export opsWithBinaryMethod := array(SymbolClosure)( PowerGreaterEqualS, UnderscoreGreaterEqualS, PowerLessS, UnderscoreLessS, PowerLessEqualS, UnderscoreLessEqualS, - PowerStarStarS, - InterpunctS, - BoxTimesS, - ShuffleProductS + PowerStarStarS ); export opsWithUnaryMethod := array(SymbolClosure)( StarS, MinusS, PlusS, LessLessS, QuestionQuestionS, diff --git a/M2/Macaulay2/m2/exports.m2 b/M2/Macaulay2/m2/exports.m2 index cff04fede4c..946eec2d2f0 100644 --- a/M2/Macaulay2/m2/exports.m2 +++ b/M2/Macaulay2/m2/exports.m2 @@ -57,9 +57,6 @@ export { "_>=", "_<", "_<=", - "·", - "⊠", - "⧢", "Acknowledgement", "AdditionalPaths", "Adjacent", diff --git a/M2/Macaulay2/m2/latex.m2 b/M2/Macaulay2/m2/latex.m2 index 069e07c86ed..c8d977eeb2b 100644 --- a/M2/Macaulay2/m2/latex.m2 +++ b/M2/Macaulay2/m2/latex.m2 @@ -127,7 +127,7 @@ keywordTexMath = applyKeys(hashTable { -- both unary and binary keywords symbol ^** => "{}^{\\otimes}", -- temporary solution to KaTeX issue https://github.com/KaTeX/KaTeX/issues/3576 symbol _* => "{}_*", -- temporary solution to KaTeX issue https://github.com/KaTeX/KaTeX/issues/3576 symbol ^* => "{}^*", -- temporary solution to KaTeX issue https://github.com/KaTeX/KaTeX/issues/3576 - symbol · => "\\cdot", +-- symbol · => "\\cdot", },symbolBody) bbLetters := set characters "kABCDEFGHIJKLMNOPQRSTUVWXYZ" diff --git a/M2/Macaulay2/tests/normal/symbols.m2 b/M2/Macaulay2/tests/normal/symbols.m2 index 3ecfde532bb..446b243dafe 100644 --- a/M2/Macaulay2/tests/normal/symbols.m2 +++ b/M2/Macaulay2/tests/normal/symbols.m2 @@ -2,4 +2,5 @@ assert (i -> symbol i === symbol i)() assert( (i -> symbol i)() =!= (i -> symbol i)() ) assert( symbolBody (i -> symbol i)() =!= symbolBody (i -> symbol i)() ) assert( f = i -> symbol i ; symbolBody f() === symbolBody f() ) - +assert( try getSymbol "" then false else true ) +assert( try getSymbol "++" then false else true ) diff --git a/M2/Macaulay2/tests/normal/unicode.m2 b/M2/Macaulay2/tests/normal/unicode.m2 index 0469edd6626..ca7e076b5e4 100644 --- a/M2/Macaulay2/tests/normal/unicode.m2 +++ b/M2/Macaulay2/tests/normal/unicode.m2 @@ -2,6 +2,7 @@ v = vector {1, 2} w = vector {3, 4} assert(v⊗w == vector {3, 4, 6, 8}) +makeKeyword("·") Vector·Vector := (v, w) -> ((transpose v#0) * w#0)_(0, 0) assert(v·w == 11) From 6449f20a10362142a76ad0a6c58efc720636c97e Mon Sep 17 00:00:00 2001 From: pzinn Date: Sun, 1 Dec 2024 00:29:07 +1100 Subject: [PATCH 13/14] fix tex Symbol/Keyword --- M2/Macaulay2/m2/latex.m2 | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/M2/Macaulay2/m2/latex.m2 b/M2/Macaulay2/m2/latex.m2 index c8d977eeb2b..e8902955127 100644 --- a/M2/Macaulay2/m2/latex.m2 +++ b/M2/Macaulay2/m2/latex.m2 @@ -89,7 +89,7 @@ keywordTexMath = applyKeys(hashTable { -- both unary and binary keywords symbol ==> => "\\Longrightarrow ", symbol <== => "\\Longleftarrow ", symbol <==> => "\\Longleftrightarrow ", - symbol _> => "{}_>", + symbol _> => "{}_>", -- temporary solution to KaTeX issue https://github.com/KaTeX/KaTeX/issues/3576 symbol _< => "{}_<", symbol ^> => "{}^>", symbol ^< => "{}^<", @@ -124,10 +124,13 @@ keywordTexMath = applyKeys(hashTable { -- both unary and binary keywords symbol |> => "\\rangle ", symbol | => "\\mid", symbol || => "\\mid\\mid", - symbol ^** => "{}^{\\otimes}", -- temporary solution to KaTeX issue https://github.com/KaTeX/KaTeX/issues/3576 - symbol _* => "{}_*", -- temporary solution to KaTeX issue https://github.com/KaTeX/KaTeX/issues/3576 - symbol ^* => "{}^*", -- temporary solution to KaTeX issue https://github.com/KaTeX/KaTeX/issues/3576 --- symbol · => "\\cdot", + symbol ^** => "{}^{\\otimes}", + symbol _* => "{}_*", + symbol ^* => "{}^*", + symbol ^<= => "{}^{\\le}", + symbol ^>= => "{}^{\\ge}", + symbol _<= => "{}_{\\le}", + symbol _>= => "{}_{\\ge}" },symbolBody) bbLetters := set characters "kABCDEFGHIJKLMNOPQRSTUVWXYZ" @@ -143,7 +146,9 @@ texMathLiteralTable := merge(texLiteralTable, "𝔴" => "\\mathfrak{w}","𝔵" => "\\mathfrak{x}","𝔶" => "\\mathfrak{y}","𝔷" => "\\mathfrak{z}","𝔄" => "\\mathfrak{A}","𝔅" => "\\mathfrak{B}","𝔆" => "\\mathfrak{C}","𝔇" => "\\mathfrak{D}","𝔈" => "\\mathfrak{E}","𝔉" => "\\mathfrak{F}","𝔊" => "\\mathfrak{G}", "𝔋" => "\\mathfrak{H}","𝔌" => "\\mathfrak{I}","𝔍" => "\\mathfrak{J}","𝔎" => "\\mathfrak{K}","𝔏" => "\\mathfrak{L}","𝔐" => "\\mathfrak{M}","𝔑" => "\\mathfrak{N}","𝔒" => "\\mathfrak{O}","𝔓" => "\\mathfrak{P}","𝔔" => "\\mathfrak{Q}","𝔕" => "\\mathfrak{R}", "𝔖" => "\\mathfrak{S}","𝔗" => "\\mathfrak{T}","𝔘" => "\\mathfrak{U}","𝔙" => "\\mathfrak{V}","𝔚" => "\\mathfrak{W}","𝔛" => "\\mathfrak{X}","𝔜" => "\\mathfrak{Y}","𝔝" => "\\mathfrak{Z}", - "×" => "\\times", "÷" => "\\div", "±" => "\\pm", + "×" => "\\times", "÷" => "\\div", "±" => "\\pm", "⊠" => "\\boxtimes", + "·" => "\\cdot", "⋯" => "\\cdots", "⋱" => "\\ddots", "⋮" => "\\vdots", "…" => "\\ldots", + "←" => "\\leftarrow", "↑" => "\\uparrow", "→" => "\\rightarrow", "↓" => "\\downarrow", "↔" => "\\leftrightarrow", "↕" => "\\updownarrow", "↖" => "\\nwarrow", "↗" => "\\nearrow", "↘" => "\\searrow", "↙" => "\\swarrow" },last) texMathLiteral = texLiteral1 texMathLiteralTable -- TODO: expand and document this behavior @@ -156,10 +161,8 @@ texVariable := x -> ( if (r := regex(suffixesRegExp, x)) =!= null then return ( r = r#1; "\\" | substring(r, x) | "{" | texVariable substring(x, 0, r#0) | "}"); if #x === 1 or regex("[^[:alnum:]]", x) =!= null then x else "\\mathit{" | x | "}") -texMathSymbol := -texMath Symbol := texVariable @@ texMathLiteral @@ toString -texMath Keyword := texMath @@ symbolBody -texMath SymbolBody := s -> if keywordTexMath#?s then keywordTexMath#s else texMathSymbol s +texMath Symbol := texMath @@ symbolBody +texMath SymbolBody := s -> if keywordTexMath#?s then keywordTexMath#s else texVariable texMathLiteral toString s -- add augmented operators removeLast := s -> substring(s,0,#s-1) From 505f978988c262f46ef36bebe62d3f8ba6817dd3 Mon Sep 17 00:00:00 2001 From: pzinn Date: Sun, 1 Dec 2024 20:47:54 +1100 Subject: [PATCH 14/14] doc makeKeyword --- M2/Macaulay2/d/binding.d | 4 +-- .../packages/Macaulay2Doc/functions.m2 | 1 + .../Macaulay2Doc/functions/makeKeyword-doc.m2 | 29 +++++++++++++++++++ 3 files changed, 32 insertions(+), 2 deletions(-) create mode 100644 M2/Macaulay2/packages/Macaulay2Doc/functions/makeKeyword-doc.m2 diff --git a/M2/Macaulay2/d/binding.d b/M2/Macaulay2/d/binding.d index 18236a2b1ac..3e6bf58c3bd 100644 --- a/M2/Macaulay2/d/binding.d +++ b/M2/Macaulay2/d/binding.d @@ -190,9 +190,9 @@ special(s:string,f:function(Token,TokenFile,int,bool):ParseTree,lprec:int,rprec: -- created below are all in the global dictionary. -- new operators must be: --- set up as an "actor" with "setup()" -- or not TODO explain +-- set up as an "actor" with "setup()" if they have nonstandard syntax +-- (without "setup()", M2 will just lookup a method) -- added to the export list in ../m2/exports.m2 --- added to the table binaryOperatorFunctions in ../m2/expressions.m2 -- added to the list of operators in the documentation node "operators" in ../packages/Macaulay2Doc/ov_language.m2 -- documented with a suitable headline, such as: -- "a unary operator" diff --git a/M2/Macaulay2/packages/Macaulay2Doc/functions.m2 b/M2/Macaulay2/packages/Macaulay2Doc/functions.m2 index 0f33fc7054d..015a2d808f4 100644 --- a/M2/Macaulay2/packages/Macaulay2Doc/functions.m2 +++ b/M2/Macaulay2/packages/Macaulay2Doc/functions.m2 @@ -153,6 +153,7 @@ load "./functions/lift-doc.m2" load "./functions/liftable-doc.m2" load "./functions/locate-doc.m2" load "./functions/LU-doc.m2" +load "./functions/makeKeyword-doc.m2" load "./functions/map-doc.m2" load "./functions/max-doc.m2" load "./functions/maxPosition-doc.m2" diff --git a/M2/Macaulay2/packages/Macaulay2Doc/functions/makeKeyword-doc.m2 b/M2/Macaulay2/packages/Macaulay2Doc/functions/makeKeyword-doc.m2 new file mode 100644 index 00000000000..4919053aa42 --- /dev/null +++ b/M2/Macaulay2/packages/Macaulay2Doc/functions/makeKeyword-doc.m2 @@ -0,0 +1,29 @@ +--- status: DRAFT +--- author(s): PZJ +--- notes: + +doc /// + Key + makeKeyword + (makeKeyword, String) + [makeKeyword, Precedence] + [makeKeyword, Syntax] + Headline + create a new keyword + Usage + makeKeyword s + Inputs + s: String + Precedence => {ZZ,Symbol} + Syntax => {List,Symbol} + Description + Text + Creates a new Keyword out of the input string. + The options specify the parsing behavior of the keyword. + Possible choices for @TT "Syntax"@ are: @TT "Binary"@, @TT "Prefix"@, @TT "Postfix"@ or @TT "{Binary,Prefix}"@. + If @TT "Precedence"@ is a @TT "Symbol"@, the precedence is set to the one of that symbol. + Example + makeKeyword("≺",Precedence => symbol <) + ZZ ≺ ZZ := (i,j) -> j==i+1 + 3≺4 +///