diff --git a/pom.xml b/pom.xml index 885035c4a5e..a376d5782fc 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ org.rascalmpl rascal - 0.40.3-RC3-SNAPSHOT + 0.40.7-SNAPSHOT jar @@ -32,7 +32,7 @@ org.rascalmpl.shell.RascalShell 2 11 - 0.27.4-RC1 + 0.28.0-RC1 @@ -181,7 +181,7 @@ maven-clean-plugin - 3.3.2 + 3.4.0 @@ -198,7 +198,7 @@ org.apache.maven.plugins maven-surefire-plugin - 3.2.5 + 3.3.1 test @@ -246,7 +246,7 @@ org.apache.maven.plugins maven-dependency-plugin - 3.6.1 + 3.7.1 @@ -262,7 +262,7 @@ org.apache.maven.plugins maven-release-plugin - 3.0.1 + 3.1.0 v@{project.version} -Drascal.compile.skip -Drascal.tutor.skip -DskipTests @@ -271,7 +271,7 @@ org.apache.maven.plugins maven-shade-plugin - 3.5.3 + 3.6.0 package @@ -323,7 +323,7 @@ org.apache.maven.plugins maven-enforcer-plugin - 3.4.1 + 3.5.0 enforce-maven @@ -416,13 +416,18 @@ org.apache.commons commons-compress - 1.26.0 + 1.26.1 com.github.luben zstd-jni 1.5.5-11 + + commons-codec + commons-codec + 1.17.0 + com.google.code.gson gson diff --git a/src/org/rascalmpl/library/IO.rsc b/src/org/rascalmpl/library/IO.rsc index b1a25b57dc5..47eb70e19f9 100644 --- a/src/org/rascalmpl/library/IO.rsc +++ b/src/org/rascalmpl/library/IO.rsc @@ -563,8 +563,11 @@ Use `readFile(file, inferCharset=false, charset=DEFAULT_CHARSET)` instead. public str readFileEnc(loc file, str charset) throws PathNotFound, IO = readFile(file, inferCharset=false, charset=charset); +@synopsis{Read the content of a file and return it as a base-64 encoded string.} +@description { +} @javaClass{org.rascalmpl.library.Prelude} -public java str readBase64(loc file) +public java str readBase64(loc file, bool includePadding=true) throws PathNotFound, IO; @deprecated{ @@ -572,15 +575,31 @@ Use readBase64 instead. Uuencode was a misnomer. } public str uuencode(loc file) = readBase64(file); +@synopsis{Decode a base-64 encoded string and write the resulting bytes to a file.} +@description { +} @javaClass{org.rascalmpl.library.Prelude} public java void writeBase64(loc file, str content) throws PathNotFound, IO; @deprecated{ -Use writeBase65 instead. Uudecode was a misnomer. +Use writeBase64 instead. Uudecode was a misnomer. } public void uudecode(loc file, str content) = writeBase64(file, content); +@synopsis{Read the content of a file and return it as a base-32 encoded string.} +@description { +} +@javaClass{org.rascalmpl.library.Prelude} +public java str readBase32(loc file, bool includePadding=true) +throws PathNotFound, IO; + +@synopsis{Decode a base-32 encoded string and write the resulting bytes to a file.} +@description { +} +@javaClass{org.rascalmpl.library.Prelude} +public java void writeBase32(loc file, str content) +throws PathNotFound, IO; @synopsis{Read the contents of a file and return it as a list of bytes.} @javaClass{org.rascalmpl.library.Prelude} @@ -692,7 +711,10 @@ public java str createLink(str title, str target); @javaClass{org.rascalmpl.library.Prelude} -public java str toBase64(loc file) +@deprecated{ + use `readBase64` instead. +} +public java str toBase64(loc file, bool includePadding=true) throws PathNotFound, IO; @javaClass{org.rascalmpl.library.Prelude} diff --git a/src/org/rascalmpl/library/Prelude.java b/src/org/rascalmpl/library/Prelude.java index 829321b3e02..1ace5a6bed3 100644 --- a/src/org/rascalmpl/library/Prelude.java +++ b/src/org/rascalmpl/library/Prelude.java @@ -51,6 +51,7 @@ import java.text.ParseException; import java.util.Arrays; import java.util.Base64; +import java.util.Base64.Encoder; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; @@ -69,6 +70,8 @@ import java.util.function.Consumer; import java.util.regex.Pattern; +import org.apache.commons.codec.CodecPolicy; +import org.apache.commons.codec.binary.Base32; import org.rascalmpl.debug.IRascalMonitor; import org.rascalmpl.exceptions.JavaCompilation; import org.rascalmpl.exceptions.RuntimeExceptionFactory; @@ -132,7 +135,7 @@ public class Prelude { private static final int FILE_BUFFER_SIZE = 8 * 1024; - + protected final URIResolverRegistry REGISTRY = URIResolverRegistry.getInstance(); protected final IValueFactory values; protected final IRascalValueFactory rascalValues; @@ -1431,12 +1434,11 @@ private IList consumeInputStreamLines(Reader in) throws IOException { } public IList readFileBytes(ISourceLocation sloc) { - if(trackIO) System.err.println("readFileBytes: " + sloc); IListWriter w = values.listWriter(); try (InputStream in = REGISTRY.getInputStream(sloc)) { - byte bytes[] = new byte[FILE_BUFFER_SIZE]; + byte[] bytes = new byte[FILE_BUFFER_SIZE]; int read; while ((read = in.read(bytes, 0, bytes.length)) != -1) { @@ -1455,9 +1457,12 @@ public IList readFileBytes(ISourceLocation sloc) { return w.done(); } - public IString readBase64(ISourceLocation sloc) { - int BUFFER_SIZE = 3 * 512; + public IString readBase64(ISourceLocation sloc, IBool includePadding) { + final int BUFFER_SIZE = 3 * 512; Base64.Encoder encoder = Base64.getEncoder(); + if (!includePadding.getValue()) { + encoder = encoder.withoutPadding(); + } try (BufferedInputStream in = new BufferedInputStream(REGISTRY.getInputStream(sloc), BUFFER_SIZE); ) { StringBuilder result = new StringBuilder(); @@ -1466,13 +1471,13 @@ public IString readBase64(ISourceLocation sloc) { // read multiples of 3 until not possible anymore while ( (len = in.read(chunk)) == BUFFER_SIZE ) { - result.append( encoder.encodeToString(chunk) ); + result.append(new String(encoder.encode(chunk), StandardCharsets.ISO_8859_1)); } // read final chunk which is not a multiple of 3 if ( len > 0 ) { chunk = Arrays.copyOf(chunk,len); - result.append( encoder.encodeToString(chunk) ); + result.append(new String(encoder.encode(chunk), StandardCharsets.ISO_8859_1)); } return values.string(result.toString()); @@ -1482,18 +1487,42 @@ public IString readBase64(ISourceLocation sloc) { } } - public void writeBase64(ISourceLocation sloc, IString contents) { - int BUFFER_SIZE = 3 * 512; + public void writeBase64(ISourceLocation sloc, IString base64content) { + final int BUFFER_SIZE = 3 * 512; Base64.Decoder decoder = Base64.getDecoder(); - try (BufferedOutputStream out = new BufferedOutputStream(REGISTRY.getOutputStream(sloc, false), BUFFER_SIZE); ) { - out.write(decoder.decode(contents.getValue())); + try (BufferedOutputStream output = new BufferedOutputStream(REGISTRY.getOutputStream(sloc, false), BUFFER_SIZE); ) { + output.write(decoder.decode(base64content.getValue())); } catch (IOException e) { throw RuntimeExceptionFactory.io(values.string(e.getMessage())); } } + public IString readBase32(ISourceLocation sloc, IBool includePadding) { + try(BufferedInputStream input = new BufferedInputStream(REGISTRY.getInputStream(sloc))) { + Base32 encoder = new Base32(); + String encoded = encoder.encodeToString(input.readAllBytes()); + if (!includePadding.getValue()) { + encoded = encoded.replace("=", ""); + } + return values.string(encoded); + } catch (IOException e) { + throw RuntimeExceptionFactory.io(values.string(e.getMessage())); + } + } + + public void writeBase32(ISourceLocation sloc, IString base32Content) { + try (BufferedOutputStream output = new BufferedOutputStream(REGISTRY.getOutputStream(sloc, false))) { + // The only relevant field we want to change set is the policy + Base32 decoder = new Base32(0, new byte[0], false, (byte) '=', CodecPolicy.LENIENT); + output.write(decoder.decode(base32Content.getValue())); + } + catch (IOException e) { + throw RuntimeExceptionFactory.io(values.string(e.getMessage())); + } + } + public IString createLink(IString title, IString target) { return values.string("\uE007["+title.getValue().replaceAll("\\]", "_")+"]("+target.getValue()+")"); } @@ -3360,50 +3389,65 @@ private void copy(Reader from, Writer to) throws IOException { } } - - private String toBase64(InputStream src, int estimatedSize) throws IOException { + private String toBase64(InputStream src, int estimatedSize, boolean includePadding) throws IOException { ByteArrayOutputStream result = new ByteArrayOutputStream(estimatedSize); - OutputStream encoder = Base64.getEncoder().wrap(result); - copy(src, encoder); - encoder.close(); + Encoder encoder = Base64.getEncoder(); + if (!includePadding) { + encoder = encoder.withoutPadding(); + } + OutputStream dest = encoder.wrap(result); + copy(src, dest); + dest.close(); return result.toString(StandardCharsets.ISO_8859_1.name()); } - public IString toBase64(IString in) { + public IString toBase64(IString in, IString charsetName, IBool includePadding) { try { - InputStream bytes = new ByteBufferBackedInputStream(StandardCharsets.UTF_8.encode(in.getValue())); - return values.string(toBase64(bytes, in.length() * 2)); + Charset charset = Charset.forName(charsetName.getValue()); + InputStream bytes = new ByteBufferBackedInputStream(charset.encode(in.getValue())); + return values.string(toBase64(bytes, in.length() * 2, includePadding.getValue())); } catch (IOException e) { throw RuntimeExceptionFactory.io(values.string(e.getMessage())); } } - public IString toBase64(ISourceLocation file) { - try (InputStream in = REGISTRY.getInputStream(file)) { - return values.string(toBase64(in, 1024)); - } - catch (IOException e) { - throw RuntimeExceptionFactory.io(values.string(e.getMessage())); - } + public IString toBase64(ISourceLocation file, IBool includePadding) { + return readBase64(file, includePadding); } - - private void fromBase64(String src, OutputStream target) throws IOException { InputStream bytes = new ByteBufferBackedInputStream(StandardCharsets.ISO_8859_1.encode(src)); copy(Base64.getDecoder().wrap(bytes), target); } - public IString fromBase64(IString in) { + public IString fromBase64(IString in, IString charset) { try { ByteArrayOutputStream result = new ByteArrayOutputStream(in.length()); fromBase64(in.getValue(), result); - return values.string(result.toString(StandardCharsets.UTF_8.name())); + return values.string(result.toString(charset.getValue())); } catch (IOException e) { throw RuntimeExceptionFactory.io(values.string(e.getMessage())); } } + public IString toBase32(IString in, IString charsetName, IBool includePadding) { + Base32 encoder = new Base32(); + Charset charset = Charset.forName(charsetName.getValue()); + String encoded = encoder.encodeToString(in.getValue().getBytes(charset)); + if (!includePadding.getValue()) { + encoded = encoded.replace("=", ""); + } + return values.string(encoded); + } + + public IString fromBase32(IString in, IString charsetName) { + // The only relevant field we want to change is the policy + Base32 decoder = new Base32(0, new byte[0], false, (byte) '=', CodecPolicy.LENIENT); + byte[] data = decoder.decode(in.getValue()); + Charset charset = Charset.forName(charsetName.getValue()); + return values.string(new String(data, charset)); + } + public IValue toLowerCase(IString s) //@doc{toLowerCase -- convert all characters in string s to lowercase.} { diff --git a/src/org/rascalmpl/library/String.rsc b/src/org/rascalmpl/library/String.rsc index 3e2cff8ab46..de466de5272 100644 --- a/src/org/rascalmpl/library/String.rsc +++ b/src/org/rascalmpl/library/String.rsc @@ -21,6 +21,8 @@ module String extend Exception; import List; +@synopsis{All functions in this module that have a charset parameter use this as default.} +private str DEFAULT_CHARSET = "UTF-8"; @synopsis{Center a string in given space.} @description{ @@ -534,11 +536,37 @@ public java str capitalize(str src); @javaClass{org.rascalmpl.library.Prelude} public java str uncapitalize(str src); +@synopsis{Base-64 encode the characters of a string.} +@description{ + Convert the characters of a string to a list of bytes using UTF-8 encoding and then encode these bytes using base-64 encoding + as defined by RFC 4648: https://www.ietf.org/rfc/rfc4648.txt. +} +@javaClass{org.rascalmpl.library.Prelude} +public java str toBase64(str src, str charset=DEFAULT_CHARSET, bool includePadding=true); + +@synopsis{Decode a base-32 encoded string.} +@description { + Convert a base-32 encoded string to bytes and then convert these bytes to a string using the specified cahracter set. + The base-32 encoding used is defined by RFC 4648: https://www.ietf.org/rfc/rfc4648.txt. +} @javaClass{org.rascalmpl.library.Prelude} -public java str toBase64(str src); +public java str fromBase64(str src, str charset=DEFAULT_CHARSET); +@synopsis{Base-32 encode the characters of a string.} +@description{ + Convert the characters of a string to a list of bytes using UTF-8 encoding and then encode these bytes using base-32 encoding + as defined by RFC 4648: https://www.ietf.org/rfc/rfc4648.txt. +} +@javaClass{org.rascalmpl.library.Prelude} +public java str toBase32(str src, str charset=DEFAULT_CHARSET, bool includePadding=true); + +@synopsis{Decode a base-32 encoded string.} +@description { + Convert a base-32 encoded string to bytes and then convert these bytes to a string using the specified cahracter set. + The base-32 encoding used is defined by RFC 4648: https://www.ietf.org/rfc/rfc4648.txt. +} @javaClass{org.rascalmpl.library.Prelude} -public java str fromBase64(str src); +public java str fromBase32(str src, str charset=DEFAULT_CHARSET); @synopsis{Word wrap a string to fit in a certain width.} diff --git a/src/org/rascalmpl/library/lang/dot/Dot.rsc b/src/org/rascalmpl/library/lang/dot/Dot.rsc index 9d731bf486c..a05d6bb9f05 100644 --- a/src/org/rascalmpl/library/lang/dot/Dot.rsc +++ b/src/org/rascalmpl/library/lang/dot/Dot.rsc @@ -117,7 +117,7 @@ private str oCompassPt(E()) = "e"; private str oCompassPt(SE()) = "se"; private str oCompassPt(S()) = "s"; private str oCompassPt(SW()) = "sw"; -private str oCompassPt(E()) = "w"; +private str oCompassPt(W()) = "w"; private str oCompassPt(NW()) = "nw"; private default str oCompassPt(CompassPt _) = "_"; diff --git a/src/org/rascalmpl/library/lang/rascal/tests/functionality/PatternList1.rsc b/src/org/rascalmpl/library/lang/rascal/tests/functionality/PatternList1.rsc index 117b680efaf..03040c4f4b3 100644 --- a/src/org/rascalmpl/library/lang/rascal/tests/functionality/PatternList1.rsc +++ b/src/org/rascalmpl/library/lang/rascal/tests/functionality/PatternList1.rsc @@ -687,6 +687,9 @@ test bool matchListSpliceVars4() = [1, * int _, 4, 5] := [1, 2, 3, 4, 5]; test bool matchListSpliceVars5() = [1, *L, 4, *L, 5] := [1, 2, 3, 4, 2, 3, 5] && L == [2, 3]; test bool matchListSpliceVars6() = [1, * int L, 4, *L, 5] := [1, 2, 3, 4, 2, 3, 5] && L == [2, 3]; +test bool matchListSpliceVarsInOr() + = [1,2,3] == (([*int x] := [1,2,3] || [*int x] := [10,20,30]) ? x : []); + // match list of tuples test bool matchListTuples1() = [<1, 2, 3>] := [<1, 2, 3>]; @@ -948,6 +951,9 @@ test bool matchTypedListVarBecomes2() = [1, list[int] L: [int _], 2] := [1,[2],2 test bool matchTypedListVarBecomes3() = [1, list[int] L1: [*int L2, int N], 5] := [1,[2,3,4],5] && L1 == [2,3,4] && L2 == [2,3] && N == 4; test bool matchTypedListVarBecomes4() = [1, list[int] L1: [*int L2, int N], L1] := [1,[2,3,4],[2,3,4]] && L1 == [2,3,4] && L2 == [2,3] && N == 4; +test bool matchTypedListVarInOr() = + 1 == (([int x: 1] := [1] || [int x: 10] := [10]) ? x : -1); + data D = d(int n); test bool listNamedElem1() = [n:d(1)] := [d(1)] && n == d(1); @@ -957,3 +963,5 @@ test bool listNamedElem3() = [_n:d(2)] !:= [d(1)]; test bool listTypeNamedElem1() = [D n:d(1)] := [d(1)] && n == d(1); test bool listTypeNamedElem2() = [D _:d(1)] := [d(1)]; test bool listTypeNamedElem3() = [D _n:d(2)] !:= [d(1)]; + + diff --git a/src/org/rascalmpl/library/lang/rascal/tests/functionality/PatternSet1.rsc b/src/org/rascalmpl/library/lang/rascal/tests/functionality/PatternSet1.rsc index 3bf764fe263..a9137121085 100644 --- a/src/org/rascalmpl/library/lang/rascal/tests/functionality/PatternSet1.rsc +++ b/src/org/rascalmpl/library/lang/rascal/tests/functionality/PatternSet1.rsc @@ -638,6 +638,12 @@ test bool matchSetSpliceVars2() = {1, * int S, 4, 5}:= {1, 2, 3, 4, 5} && S == { test bool matchSetSpliceVars3() = {1, *_, 4, 5} := {1, 2, 3, 4, 5}; test bool matchSetSpliceVars4() = {1, * int _, 4, 5} := {1, 2, 3, 4, 5}; +test bool matchSetSpliceVarInOr() + = {1,2,3} == (({*int x} := {1,2,3} || {*int x} := {10,20,30}) ? x : {}); + +test bool matchTypedSetVarInOr() = + 1 == (({int x: 1} := {1} || {int x: 10} := {10}) ? x : -1); + // match set of tuples test bool matchSetTuples1() = {<1, 2, 3>} := {<1, 2, 3>}; diff --git a/src/org/rascalmpl/library/lang/rascal/tests/library/IO.rsc b/src/org/rascalmpl/library/lang/rascal/tests/library/IO.rsc index d0ea55d2c0d..f7be0f46cc0 100644 --- a/src/org/rascalmpl/library/lang/rascal/tests/library/IO.rsc +++ b/src/org/rascalmpl/library/lang/rascal/tests/library/IO.rsc @@ -2,6 +2,7 @@ module lang::rascal::tests::library::IO import IO; import DateTime; +import String; test bool testFileCopyCompletely() { writeFile(|tmp:///longFile|, "123456789"); @@ -25,3 +26,16 @@ test bool createdDoesNotCrashOnURIRewrites() { writeFile(|tmp:///createdDoesNotCrashOnURIRewrites/someFile.txt|, "123456789"); return created(|tmp:///createdDoesNotCrashOnURIRewrites/someFile.txt|) <= now(); } + +test bool testWriteBase32() { + str original = "Hello World!"; + writeBase32(|memory:///base32Test/writeTest.txt|, toBase32(original)); + return original == readFile(|memory:///base32Test/writeTest.txt|); +} + +test bool testReadBase32() { + str original = "Hello World!"; + writeFile(|memory:///base32Test/readTest.txt|, original); + str encoded = readBase32(|memory:///base32Test/readTest.txt|); + return original == fromBase32(encoded); +} diff --git a/src/org/rascalmpl/library/lang/rascal/tests/library/String.rsc b/src/org/rascalmpl/library/lang/rascal/tests/library/String.rsc index 136cb193e4f..f806220cb4b 100644 --- a/src/org/rascalmpl/library/lang/rascal/tests/library/String.rsc +++ b/src/org/rascalmpl/library/lang/rascal/tests/library/String.rsc @@ -14,7 +14,7 @@ *******************************************************************************/ import String; - + // center test bool center1() = center("a", 0) == "a"; @@ -231,9 +231,33 @@ test bool toUpperCase2() = toUpperCase("") == ""; test bool toUpperCase3() = String::toUpperCase("abc") == "ABC"; test bool toUpperCase4() = String::toUpperCase("abc123") == "ABC123"; - - - - - - + +// Base64 +bool testBase64(str s) { + return fromBase64(toBase64(s)) == s && fromBase64(toBase64(s, includePadding=false)) == s; +} + +test bool toBase64Empty() = toBase64("") == ""; +test bool toBase64Single() = toBase64("a") == "YQ=="; +test bool toBase64SingleNoPadding() = toBase64("a", includePadding=false) == "YQ"; + +test bool testBase64SomeChars() = testBase64("Hello World!"); +test bool testBase64AllChars1() = testBase64("`1234567890-=~!@#$%^&*"); +test bool testBase64AllChars2() = testBase64("()_+qwertyuiop[]\\QWERTYUIOP"); +test bool testBase64AllChars3() = testBase64("{}|asdfghjkl;\'ASDFGHJKL:\""); +test bool testBase64AllChars4() = testBase64("zxcvbnm,./ZXCVBNM\<\>? "); + +// Base32 +bool testBase32(str s) { + return fromBase32(toBase32(s)) == s && fromBase32(toBase32(s, includePadding=false)) == s; +} + +test bool toBase32Empty() = toBase32("") == ""; +test bool toBase32EmptyNoPadding() = toBase32("", includePadding=false) == ""; +test bool toBase32Single() = toBase32("a") == "ME======"; +test bool toBase32SingleNoPadding() = toBase32("a", includePadding=false) == "ME"; +test bool testBase32SomeChars() = testBase32("Hello World!"); +test bool testBase32AllChars1() = testBase32("`1234567890-=~!@#$%^&*"); +test bool testBase32AllChars2() = testBase32("()_+qwertyuiop[]\\QWERTYUIOP"); +test bool testBase32AllChars3() = testBase32("{}|asdfghjkl;\'ASDFGHJKL:\""); +test bool testBase32AllChars4() = testBase32("zxcvbnm,./ZXCVBNM\<\>? "); diff --git a/src/org/rascalmpl/library/lang/rsf/IO.rsc b/src/org/rascalmpl/library/lang/rsf/IO.rsc index 64e58e309c2..b65f0fc4b71 100644 --- a/src/org/rascalmpl/library/lang/rsf/IO.rsc +++ b/src/org/rascalmpl/library/lang/rsf/IO.rsc @@ -18,9 +18,6 @@ where each field is separated by a tabulation character (\t). One file may conta @javaClass{org.rascalmpl.library.lang.rsf.RSFIO} public java map[str, rel[str,str]] readRSF(loc nameRSFFile); -@javaClass{org.rascalmpl.library.lang.rsf.RSFIO} -public java map[str, rel[str,str]] readRSF(loc nameRSFFile); - @javaClass{org.rascalmpl.library.lang.rsf.RSFIO} public java map[str, type[value]] getRSFTypes(loc location); diff --git a/src/org/rascalmpl/library/lang/sdf2/util/SDF2Grammar.rsc b/src/org/rascalmpl/library/lang/sdf2/util/SDF2Grammar.rsc index 320200f437a..227fbcda874 100644 --- a/src/org/rascalmpl/library/lang/sdf2/util/SDF2Grammar.rsc +++ b/src/org/rascalmpl/library/lang/sdf2/util/SDF2Grammar.rsc @@ -28,17 +28,13 @@ public Symbol label(str s, conditional(Symbol t, set[Condition] cs)) = condition public Symbol conditional(conditional(Symbol s, set[Condition] c1), set[Condition] c2) = conditional(s, c1 + c2); public GrammarDefinition sdf2grammar(loc input) { - return sdf2grammar("Main", parse(#SDF, input)); + return sdf2grammar("Main", input); } public GrammarDefinition sdf2grammar(str main, loc input) { return sdf2grammar(main, parse(#SDF, input)); } -public GrammarDefinition sdf2grammar(loc input) { - return sdf2grammar(parse(#SDF, input)); -} - public GrammarDefinition sdf2grammar(SDF def) { return sdf2grammar("Main", def); } diff --git a/src/org/rascalmpl/library/util/Maybe.rsc b/src/org/rascalmpl/library/util/Maybe.rsc index a2e42888c52..30a80d4b1a7 100644 --- a/src/org/rascalmpl/library/util/Maybe.rsc +++ b/src/org/rascalmpl/library/util/Maybe.rsc @@ -11,9 +11,25 @@ module util::Maybe @synopsis{Generic data type to encapsulate any value, optionally.} @examples{ +```rascal-shell +import util::Maybe; +// nothing() can always be assigned to a variable of type `Maybe[Anytype]` +Maybe[int] myIntOption = nothing(); +// another example of the same feature: +Maybe[str] myStrOption = nothing(); +// if you do have a value, the type of the parameter of `just` must align: +myStrOption = just("a string"); +``` + +If you don't align the type of the parameter with the parameter type of `Maybe`, static errors ensue: +```rascal-shell-continue-error +myStrOption = just(42); +``` + +Here's a function that sometimes returns a value and otherwise returns `nothing()`: ```rascal -Maybe[int] indexOf(list[int] l, int toFind) { - for (i <- index(l), l[i] == toFind) { +Maybe[int] indexOf(list[int] haystack, int needle) { + for (i <- index(haystack), haystack[i] == needle) { return just(i); } diff --git a/src/org/rascalmpl/shell/ModuleRunner.java b/src/org/rascalmpl/shell/ModuleRunner.java index 63ff6c51530..7d78fd3c00b 100644 --- a/src/org/rascalmpl/shell/ModuleRunner.java +++ b/src/org/rascalmpl/shell/ModuleRunner.java @@ -27,11 +27,11 @@ public void run(String args[]) throws IOException { } module = module.replaceAll("/", "::"); - eval.doImport(null, module); + eval.doImport(eval.getMonitor(), module); String[] realArgs = new String[args.length - 1]; System.arraycopy(args, 1, realArgs, 0, args.length - 1); - IValue v = eval.main(null, module, "main", realArgs); + IValue v = eval.main(eval.getMonitor(), module, "main", realArgs); if (v != null && !(v instanceof IInteger)) { new StandardTextWriter(true).write(v, eval.getOutPrinter());