}
}
@Override
public <U extends IValue> Result<U> fieldAccess(String name, TypeStore store) {
IValueFactory vf = getValueFactory();
TypeFactory tf = getTypeFactory();
ISourceLocation value = getValue();
String stringResult = null;
Integer intResult = null;
Integer tupleA = null;
Integer tupleB = null;
switch (name) {
case "scheme":
stringResult = value.getScheme();
break;
case "authority":
stringResult = value.hasAuthority() ? value.getAuthority() : "";
break;
case "host":
case "user":
case "port":
URI uri = value.getURI();
if (!ctx.getResolverRegistry().supportsHost(uri)) {
throw new UndeclaredField(name, "The scheme " + uri.getScheme() + " does not support the " + name + " field, use authority instead.", tf.sourceLocationType(), ctx.getCurrentAST());
}
if (name.equals("host")) {
stringResult = uri.getHost();
}
else if (name.equals("user")) {
stringResult = uri.getUserInfo();
}
else {
intResult = uri.getPort();
}
if (stringResult == null && intResult == null) {
stringResult = "";
}
break;
case "path":
stringResult = value.hasPath() ? value.getPath() : "";
break;
case "query":
stringResult = value.hasQuery() ? value.getQuery() : "";
break;
case "fragment":
stringResult = value.hasFragment() ? value.getFragment() : "";
break;
case "length":
if (value.hasOffsetLength()) {
intResult = value.getLength();
break;
}
throw RuntimeExceptionFactory.unavailableInformation(ctx.getCurrentAST(), ctx.getStackTrace());
case "offset":
if (value.hasOffsetLength()) {
intResult = value.getOffset();
break;
}
throw RuntimeExceptionFactory.unavailableInformation(ctx.getCurrentAST(), ctx.getStackTrace());
case "begin":
if (value.hasLineColumn()) {
tupleA = value.getBeginLine();
tupleB = value.getBeginColumn();
break;
}
throw RuntimeExceptionFactory.unavailableInformation(ctx.getCurrentAST(), ctx.getStackTrace());
case "end":
if (value.hasLineColumn()) {
tupleA = value.getEndLine();
tupleB = value.getEndColumn();
break;
}
throw RuntimeExceptionFactory.unavailableInformation(ctx.getCurrentAST(), ctx.getStackTrace());
case "uri":
stringResult = value.getURI().toString();
break;
case "top":
return makeResult(tf.sourceLocationType(), vf.sourceLocation(value.getURI()), ctx);
// now the calculated fields
case "parent": {
String path = value.hasPath() ? value.getPath() : "";
if (path.equals("") || path.equals("/")) {
throw RuntimeExceptionFactory.noParent(getValue(), ctx.getCurrentAST(), ctx.getStackTrace());
}
// remove one or more /'s at the end
if (path.endsWith("/")) {
path = path.substring(0, path.length() -1);
}
int i = path.lastIndexOf((int)'/');
if (i != -1) {
path = path.substring(0, i);
if (value.getScheme().equalsIgnoreCase("file")) {
// there is a special case for file references to windows paths.
// the root path should end with a / (c:/ not c:)
if (path.lastIndexOf((int)'/') == 0 && path.endsWith(":")) {
path += "/";
}
}
return fieldUpdate("path", makeResult(tf.stringType(), vf.string(path), ctx), store);
}
throw RuntimeExceptionFactory.noParent(getValue(), ctx.getCurrentAST(), ctx.getStackTrace());
}
case "file": {
String path = value.hasPath() ? value.getPath() : "";
if (path.equals("")) {
throw RuntimeExceptionFactory.noParent(getValue(), ctx.getCurrentAST(), ctx.getStackTrace());
}
int i = path.lastIndexOf((int)'/');
if (i != -1) {
stringResult = path.substring(i+1);
}
else {
stringResult = path;
}
break;
}
case "ls": {
try {
ISourceLocation resolved = ctx.getHeap().resolveSourceLocation(value);
if (!ctx.getResolverRegistry().isDirectory(resolved.getURI())) {
throw RuntimeExceptionFactory.io(vf.string("You can only access ls on a directory, or a container."), ctx.getCurrentAST(), ctx.getStackTrace());
}
Result<IValue> resRes = makeResult(getType(), resolved, ctx);
IListWriter w = ctx.getValueFactory().listWriter();
Type stringType = tf.stringType();
for (String elem : ctx.getResolverRegistry().listEntries(resolved.getURI())) {
w.append(resRes.add(makeResult(stringType, vf.string(elem), ctx)).getValue());
}
IList result = w.done();
// a list of loc's
return makeResult(result.getType(), result, ctx);
} catch (IOException e) {
throw RuntimeExceptionFactory.io(vf.string(e.getMessage()), ctx.getCurrentAST(), ctx.getStackTrace());
}
}
case "extension" : {
String path = value.hasPath() ? value.getPath() : "";
int i = path.lastIndexOf((int)'.');
if (i != -1) {
stringResult = path.substring(i + 1);
}
else {
stringResult = "";
}
break;
}
case "params" : {
String query = value.hasQuery() ? value.getQuery() : "";
IMapWriter res = vf.mapWriter(tf.stringType(), tf.stringType());
if (query != null && query.length() > 0) {
String[] params = query.split("&");
for (String param : params) {
String[] keyValue = param.split("=");
res.put(vf.string(keyValue[0]), vf.string(keyValue[1]));
}
}
IMap map = res.done();
return makeResult(map.getType(), map, ctx);
}
default:
throw new UndeclaredField(name, getTypeFactory().sourceLocationType(), ctx.getCurrentAST());
}
if (stringResult != null) {
return makeResult(tf.stringType(), vf.string(stringResult), ctx);
}
if (intResult != null) {
return makeResult(tf.integerType(), vf.integer(intResult), ctx);
}
if (tupleA != null && tupleB != null) {
return makeResult(intTuple, vf.tuple(vf.integer(tupleA), vf.integer(tupleB)), ctx);
}
throw new RuntimeException("A case not handled? " + name);
}