Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

User-defined keywords #3599

Open
wants to merge 14 commits into
base: development
Choose a base branch
from
2 changes: 2 additions & 0 deletions M2/Macaulay2/d/actors2.dd
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
183 changes: 50 additions & 133 deletions M2/Macaulay2/d/actors5.d
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
-- Copyright 1995,2010 by Daniel R. Grayson
use actors;
use actors2;
use binding;

header "#include <interface/random.h>";

Expand All @@ -13,26 +14,45 @@ getParsing(e:Expr):Expr := (
else nullE);
setupfun("getParsing",getParsing);

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);
export makeKeywordFun(e:Expr):Expr := (
when e
is seq:Sequence do
if length(seq) != 4
then WrongNumArgs(4)
else (
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 (
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);
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 (
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")
else WrongArg(1,"a string")
)
else WrongNumArgs(4)
);
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 := (
Expand Down Expand Up @@ -137,108 +157,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
Expand All @@ -256,9 +174,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
Expand All @@ -280,11 +195,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
Expand Down Expand Up @@ -1597,8 +1507,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 "+s+" is a keyword") else createSymbol(w, d, s)
);

getglobalsym(s:string):Expr := (
w := makeUniqueWord(s,parseWORD);
Expand Down Expand Up @@ -2091,7 +2003,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);
Expand Down
75 changes: 14 additions & 61 deletions M2/Macaulay2/d/binding.d
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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()"
-- 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"
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -643,18 +636,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 := (
foreach s in opsWithBinaryMethod do if s.symbol == o then return true;
return false;
);
opHasUnaryMethod(o:Symbol):bool := (
foreach s in opsWithUnaryMethod do if s.symbol == o then return true;
return false;
);
opHasPostfixMethod(o:Symbol):bool := (
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);
Expand Down Expand Up @@ -715,54 +696,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 (
Expand Down
Loading
Loading