PageRenderTime 47ms CodeModel.GetById 12ms RepoModel.GetById 1ms app.codeStats 0ms

/src/org/rascalmpl/library/Prelude.java

https://github.com/jimivdw/rascal
Java | 3276 lines | 2864 code | 256 blank | 156 comment | 199 complexity | e246167e580352ac788e8e65641b2aef MD5 | raw file

Large files files are truncated, but you can click here to view the full file

  1. /*******************************************************************************
  2. * Copyright (c) 2009-2013 CWI
  3. * All rights reserved. This program and the accompanying materials
  4. * are made available under the terms of the Eclipse Public License v1.0
  5. * which accompanies this distribution, and is available at
  6. * http://www.eclipse.org/legal/epl-v10.html
  7. *
  8. * Contributors:
  9. * * Paul Klint - Paul.Klint@cwi.nl - CWI
  10. * * Jurgen J. Vinju - Jurgen.Vinju@cwi.nl - CWI
  11. * * Arnold Lankamp - Arnold.Lankamp@cwi.nl
  12. * * Davy Landman - Davy.Landman@cwi.nl
  13. * * Michael Steindorfer - Michael.Steindorfer@cwi.nl - CWI
  14. *******************************************************************************/
  15. /*******************************************************************************
  16. *
  17. * Warning this file is an experiment to determine the effect of collecting all
  18. * classes used by the Prelude in a single class. Overall effect seems to be circa 10%
  19. * reduction of import time.
  20. *
  21. * Do not edit/change this code, but use the original code instead.
  22. *
  23. */
  24. package org.rascalmpl.library;
  25. import java.io.BufferedInputStream;
  26. import java.io.BufferedReader;
  27. import java.io.FileInputStream;
  28. import java.io.FileNotFoundException;
  29. import java.io.FileReader;
  30. import java.io.IOException;
  31. import java.io.InputStream;
  32. import java.io.InputStreamReader;
  33. import java.io.OutputStream;
  34. import java.io.OutputStreamWriter;
  35. import java.io.PrintWriter;
  36. import java.io.Reader;
  37. import java.io.StringReader;
  38. import java.lang.ref.WeakReference;
  39. import java.math.BigInteger;
  40. import java.net.MalformedURLException;
  41. import java.nio.charset.Charset;
  42. import java.security.DigestInputStream;
  43. import java.security.MessageDigest;
  44. import java.security.NoSuchAlgorithmException;
  45. import java.text.ParseException;
  46. import java.util.Comparator;
  47. import java.util.HashMap;
  48. import java.util.HashSet;
  49. import java.util.Iterator;
  50. import java.util.LinkedList;
  51. import java.util.Locale;
  52. import java.util.Map;
  53. import java.util.Map.Entry;
  54. import java.util.PriorityQueue;
  55. import java.util.Random;
  56. import java.util.Set;
  57. import java.util.regex.Pattern;
  58. import org.apache.commons.lang.CharSetUtils;
  59. import org.apache.commons.lang.WordUtils;
  60. import org.eclipse.imp.pdb.facts.IBool;
  61. import org.eclipse.imp.pdb.facts.IConstructor;
  62. import org.eclipse.imp.pdb.facts.IDateTime;
  63. import org.eclipse.imp.pdb.facts.IInteger;
  64. import org.eclipse.imp.pdb.facts.IList;
  65. import org.eclipse.imp.pdb.facts.IListRelation;
  66. import org.eclipse.imp.pdb.facts.IListWriter;
  67. import org.eclipse.imp.pdb.facts.IMap;
  68. import org.eclipse.imp.pdb.facts.IMapWriter;
  69. import org.eclipse.imp.pdb.facts.INode;
  70. import org.eclipse.imp.pdb.facts.IRational;
  71. import org.eclipse.imp.pdb.facts.IRelation;
  72. import org.eclipse.imp.pdb.facts.IRelationWriter;
  73. import org.eclipse.imp.pdb.facts.ISet;
  74. import org.eclipse.imp.pdb.facts.ISetWriter;
  75. import org.eclipse.imp.pdb.facts.ISourceLocation;
  76. import org.eclipse.imp.pdb.facts.IString;
  77. import org.eclipse.imp.pdb.facts.ITuple;
  78. import org.eclipse.imp.pdb.facts.IValue;
  79. import org.eclipse.imp.pdb.facts.IValueFactory;
  80. import org.eclipse.imp.pdb.facts.exceptions.FactTypeUseException;
  81. import org.eclipse.imp.pdb.facts.io.ATermReader;
  82. import org.eclipse.imp.pdb.facts.io.BinaryValueReader;
  83. import org.eclipse.imp.pdb.facts.io.BinaryValueWriter;
  84. import org.eclipse.imp.pdb.facts.io.StandardTextReader;
  85. import org.eclipse.imp.pdb.facts.io.StandardTextWriter;
  86. import org.eclipse.imp.pdb.facts.type.Type;
  87. import org.eclipse.imp.pdb.facts.type.TypeFactory;
  88. import org.eclipse.imp.pdb.facts.type.TypeStore;
  89. import org.eclipse.imp.pdb.facts.visitors.VisitorException;
  90. import org.rascalmpl.interpreter.IEvaluatorContext;
  91. import org.rascalmpl.interpreter.TypeReifier;
  92. import org.rascalmpl.interpreter.asserts.ImplementationError;
  93. import org.rascalmpl.interpreter.control_exceptions.Throw;
  94. import org.rascalmpl.interpreter.result.ICallableValue;
  95. import org.rascalmpl.interpreter.staticErrors.UndeclaredNonTerminal;
  96. import org.rascalmpl.interpreter.types.FunctionType;
  97. import org.rascalmpl.interpreter.types.NonTerminalType;
  98. import org.rascalmpl.interpreter.types.ReifiedType;
  99. import org.rascalmpl.interpreter.utils.RuntimeExceptionFactory;
  100. import org.rascalmpl.parser.gtd.exception.ParseError;
  101. import org.rascalmpl.parser.gtd.exception.UndeclaredNonTerminalException;
  102. import org.rascalmpl.unicode.UnicodeDetector;
  103. import org.rascalmpl.unicode.UnicodeOutputStreamWriter;
  104. import org.rascalmpl.values.uptr.Factory;
  105. import org.rascalmpl.values.uptr.ProductionAdapter;
  106. import org.rascalmpl.values.uptr.SymbolAdapter;
  107. import org.rascalmpl.values.uptr.TreeAdapter;
  108. import org.rascalmpl.values.uptr.visitors.TreeVisitor;
  109. import com.ibm.icu.text.SimpleDateFormat;
  110. import com.ibm.icu.util.Calendar;
  111. import com.ibm.icu.util.TimeZone;
  112. import com.ibm.icu.util.ULocale;
  113. public class Prelude {
  114. private final TypeFactory types ;
  115. private final IValueFactory values;
  116. private final Random random;
  117. public Prelude(IValueFactory values){
  118. super();
  119. this.values = values;
  120. this.types = TypeFactory.getInstance();
  121. this.tr = new TypeReifier(values);
  122. random = new Random();
  123. }
  124. /* // Only here for test purposes:
  125. public IValue f1(IInteger x, IInteger y){
  126. return values.integer(x.intValue() + y.intValue());
  127. }
  128. public IValue f2(IInteger x, IList LS, IString y, IBool z){
  129. return values.string("x : " + x.intValue() + ", LS = " + LS + ", y ; " + y + ", z : " + z);
  130. }
  131. */
  132. /*
  133. * Boolean
  134. */
  135. public IValue arbBool() // get an arbitrary boolean value.}
  136. {
  137. return values.bool(random.nextInt(2) == 1);
  138. }
  139. /*
  140. * DateTime
  141. */
  142. public IValue now()
  143. //@doc{Get the current datetime.}
  144. {
  145. return values.datetime(Calendar.getInstance().getTimeInMillis());
  146. }
  147. public IValue createDate(IInteger year, IInteger month, IInteger day)
  148. //@doc{Create a new date.}
  149. {
  150. return values.date(year.intValue(), month.intValue(), day.intValue());
  151. }
  152. public IValue createTime(IInteger hour, IInteger minute, IInteger second,
  153. IInteger millisecond)
  154. //@doc{Create a new time.}
  155. {
  156. return values.time(hour.intValue(), minute.intValue(), second.intValue(), millisecond.intValue());
  157. }
  158. public IValue createTime(IInteger hour, IInteger minute, IInteger second,
  159. IInteger millisecond, IInteger timezoneHourOffset, IInteger timezoneMinuteOffset)
  160. //@doc{Create a new time with the given numeric timezone offset.}
  161. {
  162. return values.time(hour.intValue(), minute.intValue(), second.intValue(),
  163. millisecond.intValue(), timezoneHourOffset.intValue(), timezoneMinuteOffset.intValue());
  164. }
  165. public IValue createDateTime(IInteger year, IInteger month, IInteger day,
  166. IInteger hour, IInteger minute, IInteger second, IInteger millisecond)
  167. //@doc{Create a new datetime.}
  168. {
  169. return values.datetime(year.intValue(), month.intValue(), day.intValue(), hour.intValue(),
  170. minute.intValue(), second.intValue(), millisecond.intValue());
  171. }
  172. public IValue createDateTime(IInteger year, IInteger month, IInteger day,
  173. IInteger hour, IInteger minute, IInteger second, IInteger millisecond,
  174. IInteger timezoneHourOffset, IInteger timezoneMinuteOffset)
  175. //@doc{Create a new datetime with the given numeric timezone offset.}
  176. {
  177. return values.datetime(year.intValue(), month.intValue(), day.intValue(), hour.intValue(),
  178. minute.intValue(), second.intValue(), millisecond.intValue(), timezoneHourOffset.intValue(),
  179. timezoneMinuteOffset.intValue());
  180. }
  181. public IValue joinDateAndTime(IDateTime date, IDateTime time)
  182. //@doc{Create a new datetime by combining a date and a time.}
  183. {
  184. return values.datetime(date.getYear(), date.getMonthOfYear(), date.getDayOfMonth(),
  185. time.getHourOfDay(), time.getMinuteOfHour(), time.getSecondOfMinute(),
  186. time.getMillisecondsOfSecond(), time.getTimezoneOffsetHours(), time.getTimezoneOffsetMinutes());
  187. }
  188. public IValue splitDateTime(IDateTime dt)
  189. //@doc{Split an existing datetime into a tuple with the date and the time.}
  190. {
  191. return values.tuple(values.date(dt.getYear(), dt.getMonthOfYear(), dt.getDayOfMonth()),
  192. values.time(dt.getHourOfDay(), dt.getMinuteOfHour(), dt.getSecondOfMinute(),
  193. dt.getMillisecondsOfSecond(), dt.getTimezoneOffsetHours(), dt.getTimezoneOffsetMinutes()));
  194. }
  195. public IValue incrementYears(IDateTime dt, IInteger n)
  196. //@doc{Increment the years by a given amount.}
  197. {
  198. return incrementDate(dt, Calendar.YEAR, "years", n);
  199. }
  200. public IValue incrementMonths(IDateTime dt, IInteger n)
  201. //@doc{Increment the months by a given amount.}
  202. {
  203. return incrementDate(dt, Calendar.MONTH, "months", n);
  204. }
  205. public IValue incrementDays(IDateTime dt, IInteger n)
  206. //@doc{Increment the days by a given amount.}
  207. {
  208. return incrementDate(dt, Calendar.DAY_OF_MONTH, "days", n);
  209. }
  210. private String getTZString(int hourOffset, int minuteOffset) {
  211. String tzString = "GMT" +
  212. ((hourOffset < 0 || (0 == hourOffset && minuteOffset < 0)) ? "-" : "+") +
  213. String.format("%02d",hourOffset >= 0 ? hourOffset : hourOffset * -1) +
  214. String.format("%02d",minuteOffset >= 0 ? minuteOffset : minuteOffset * -1);
  215. return tzString;
  216. }
  217. private final int millisInAMinute = 1000 * 60;
  218. private final int millisInAnHour = millisInAMinute * 60;
  219. private IValue incrementDTField(IDateTime dt, int field, IInteger amount) {
  220. Calendar cal = null;
  221. cal = dateTimeToCalendar(dt);
  222. // Make sure lenient is true, since this allows wrapping of fields. For
  223. // instance, if you have $2012-05-15, and subtract 15 months, this is
  224. // an error if lenient is false, but gives $2012-02-15 (as expected)
  225. // if lenient is true.
  226. cal.setLenient(true);
  227. cal.add(field, amount.intValue());
  228. // Turn the calendar back into a date, time, or datetime value
  229. if (dt.isDate()) {
  230. return calendarToDate(cal);
  231. } else {
  232. if (dt.isTime()) {
  233. return calendarToTime(cal);
  234. } else {
  235. return calendarToDateTime(cal);
  236. }
  237. }
  238. }
  239. private IValue calendarToDateTime(Calendar cal) {
  240. int timezoneHours = cal.get(Calendar.ZONE_OFFSET) / millisInAnHour;
  241. int timezoneMinutes = cal.get(Calendar.ZONE_OFFSET) % millisInAnHour / millisInAMinute;
  242. return createDateTime(values.integer(cal.get(Calendar.YEAR)),
  243. values.integer(cal.get(Calendar.MONTH)+1),
  244. values.integer(cal.get(Calendar.DAY_OF_MONTH)),
  245. values.integer(cal.get(Calendar.HOUR_OF_DAY)),
  246. values.integer(cal.get(Calendar.MINUTE)),
  247. values.integer(cal.get(Calendar.SECOND)),
  248. values.integer(cal.get(Calendar.MILLISECOND)),
  249. values.integer(timezoneHours),
  250. values.integer(timezoneMinutes));
  251. }
  252. private IValue calendarToTime(Calendar cal) {
  253. int timezoneHours = cal.get(Calendar.ZONE_OFFSET) / millisInAnHour;
  254. int timezoneMinutes = cal.get(Calendar.ZONE_OFFSET) % millisInAnHour / millisInAMinute;
  255. return createTime(values.integer(cal.get(Calendar.HOUR_OF_DAY)),
  256. values.integer(cal.get(Calendar.MINUTE)),
  257. values.integer(cal.get(Calendar.SECOND)),
  258. values.integer(cal.get(Calendar.MILLISECOND)),
  259. values.integer(timezoneHours),
  260. values.integer(timezoneMinutes));
  261. }
  262. private IValue calendarToDate(Calendar cal) {
  263. return createDate(values.integer(cal.get(Calendar.YEAR)),
  264. values.integer(cal.get(Calendar.MONTH)+1),
  265. values.integer(cal.get(Calendar.DAY_OF_MONTH)));
  266. }
  267. private Calendar dateTimeToCalendar(IDateTime dt) {
  268. Calendar cal;
  269. if (dt.isDate()) {
  270. cal = Calendar.getInstance(TimeZone.getDefault(), Locale.getDefault());
  271. cal.set(dt.getYear(), dt.getMonthOfYear()-1, dt.getDayOfMonth());
  272. } else {
  273. cal = Calendar.getInstance(TimeZone.getTimeZone(getTZString(dt.getTimezoneOffsetHours(), dt.getTimezoneOffsetMinutes())),Locale.getDefault());
  274. if (dt.isTime()) {
  275. cal.set(1970, 0, 1, dt.getHourOfDay(), dt.getMinuteOfHour(), dt.getSecondOfMinute());
  276. } else {
  277. cal.set(dt.getYear(), dt.getMonthOfYear()-1, dt.getDayOfMonth(), dt.getHourOfDay(), dt.getMinuteOfHour(), dt.getSecondOfMinute());
  278. }
  279. cal.set(Calendar.MILLISECOND, dt.getMillisecondsOfSecond());
  280. }
  281. return cal;
  282. }
  283. private IValue incrementTime(IDateTime dt, int field, String fieldName, IInteger amount) {
  284. if (dt.isDate())
  285. throw RuntimeExceptionFactory.invalidUseOfDateException("Cannot increment the " + fieldName + " on a date value.", null, null);
  286. return incrementDTField(dt, field, amount);
  287. }
  288. private IValue incrementDate(IDateTime dt, int field, String fieldName, IInteger amount) {
  289. if (dt.isTime())
  290. throw RuntimeExceptionFactory.invalidUseOfDateException("Cannot increment the " + fieldName + " on a time value.", null, null);
  291. return incrementDTField(dt, field, amount);
  292. }
  293. public IValue incrementHours(IDateTime dt, IInteger n)
  294. //@doc{Increment the hours by a given amount.}
  295. {
  296. return incrementTime(dt, Calendar.HOUR_OF_DAY, "hours", n);
  297. }
  298. public IValue incrementMinutes(IDateTime dt, IInteger n)
  299. //@doc{Increment the minutes by a given amount.}
  300. {
  301. return incrementTime(dt, Calendar.MINUTE, "minutes", n);
  302. }
  303. public IValue incrementSeconds(IDateTime dt, IInteger n)
  304. //@doc{Increment the seconds by a given amount.}
  305. {
  306. return incrementTime(dt, Calendar.SECOND, "seconds", n);
  307. }
  308. public IValue incrementMilliseconds(IDateTime dt, IInteger n)
  309. //@doc{Increment the milliseconds by a given amount.}
  310. {
  311. return incrementTime(dt, Calendar.MILLISECOND, "milliseconds", n);
  312. }
  313. public IValue decrementYears(IDateTime dt, IInteger n)
  314. //@doc{Decrement the years by a given amount.}
  315. {
  316. return incrementDate(dt, Calendar.YEAR, "years", n.negate());
  317. }
  318. public IValue decrementMonths(IDateTime dt, IInteger n)
  319. //@doc{Decrement the months by a given amount.}
  320. {
  321. return incrementDate(dt, Calendar.MONTH, "months", n.negate()); }
  322. public IValue decrementDays(IDateTime dt, IInteger n)
  323. //@doc{Decrement the days by a given amount.}
  324. {
  325. return incrementDate(dt, Calendar.DAY_OF_MONTH, "days", n.negate());
  326. }
  327. public IValue decrementHours(IDateTime dt, IInteger n)
  328. //@doc{Decrement the hours by a given amount.}
  329. {
  330. return incrementTime(dt, Calendar.HOUR_OF_DAY, "hours", n.negate());
  331. }
  332. public IValue decrementMinutes(IDateTime dt, IInteger n)
  333. //@doc{Decrement the minutes by a given amount.}
  334. {
  335. return incrementTime(dt, Calendar.MINUTE, "minutes", n.negate());
  336. }
  337. public IValue decrementSeconds(IDateTime dt, IInteger n)
  338. //@doc{Decrement the seconds by a given amount.}
  339. {
  340. return incrementTime(dt, Calendar.SECOND, "seconds", n.negate());
  341. }
  342. public IValue decrementMilliseconds(IDateTime dt, IInteger n)
  343. //@doc{Decrement the milliseconds by a given amount.}
  344. {
  345. return incrementTime(dt, Calendar.MILLISECOND, "milliseconds", n.negate());
  346. }
  347. public IValue createDurationInternal(IDateTime dStart, IDateTime dEnd) {
  348. // dStart and dEnd both have to be dates, times, or datetimes
  349. Calendar startCal = Calendar.getInstance();
  350. startCal.setTimeInMillis(dStart.getInstant());
  351. Calendar endCal = Calendar.getInstance();
  352. endCal.setTimeInMillis(dEnd.getInstant());
  353. IValue duration = null;
  354. if (dStart.isDate()) {
  355. if (dEnd.isDate()) {
  356. duration = values.tuple(
  357. values.integer(startCal.fieldDifference(endCal.getTime(), Calendar.YEAR)),
  358. values.integer(startCal.fieldDifference(endCal.getTime(), Calendar.MONTH)),
  359. values.integer(startCal.fieldDifference(endCal.getTime(), Calendar.DAY_OF_MONTH)),
  360. values.integer(0), values.integer(0), values.integer(0),
  361. values.integer(0));
  362. } else if (dEnd.isTime()) {
  363. throw RuntimeExceptionFactory.invalidUseOfTimeException("Cannot determine the duration between a date with no time and a time with no date.", null, null);
  364. } else {
  365. throw RuntimeExceptionFactory.invalidUseOfDateTimeException("Cannot determine the duration between a date with no time and a datetime.", null, null);
  366. }
  367. } else if (dStart.isTime()) {
  368. if (dEnd.isTime()) {
  369. duration = values.tuple(
  370. values.integer(0),
  371. values.integer(0),
  372. values.integer(0),
  373. values.integer(startCal.fieldDifference(endCal.getTime(), Calendar.HOUR_OF_DAY)),
  374. values.integer(startCal.fieldDifference(endCal.getTime(), Calendar.MINUTE)),
  375. values.integer(startCal.fieldDifference(endCal.getTime(), Calendar.SECOND)),
  376. values.integer(startCal.fieldDifference(endCal.getTime(), Calendar.MILLISECOND)));
  377. } else if (dEnd.isDate()) {
  378. throw RuntimeExceptionFactory.invalidUseOfDateException("Cannot determine the duration between a time with no date and a date with no time.", null, null);
  379. } else {
  380. throw RuntimeExceptionFactory.invalidUseOfDateTimeException("Cannot determine the duration between a time with no date and a datetime.", null, null);
  381. }
  382. } else {
  383. if (dEnd.isDateTime()) {
  384. duration = values.tuple(
  385. values.integer(startCal.fieldDifference(endCal.getTime(), Calendar.YEAR)),
  386. values.integer(startCal.fieldDifference(endCal.getTime(), Calendar.MONTH)),
  387. values.integer(startCal.fieldDifference(endCal.getTime(), Calendar.DAY_OF_MONTH)),
  388. values.integer(startCal.fieldDifference(endCal.getTime(), Calendar.HOUR_OF_DAY)),
  389. values.integer(startCal.fieldDifference(endCal.getTime(), Calendar.MINUTE)),
  390. values.integer(startCal.fieldDifference(endCal.getTime(), Calendar.SECOND)),
  391. values.integer(startCal.fieldDifference(endCal.getTime(), Calendar.MILLISECOND)));
  392. } else if (dEnd.isDate()) {
  393. throw RuntimeExceptionFactory.invalidUseOfDateException("Cannot determine the duration between a datetime and a date with no time.", null, null);
  394. } else {
  395. throw RuntimeExceptionFactory.invalidUseOfTimeException("Cannot determine the duration between a datetime and a time with no date.", null, null);
  396. }
  397. }
  398. return duration;
  399. }
  400. public IValue parseDate(IString inputDate, IString formatString)
  401. //@doc{Parse an input date given as a string using the given format string}
  402. {
  403. try {
  404. java.text.SimpleDateFormat fmt = new java.text.SimpleDateFormat(formatString.getValue());
  405. fmt.parse(inputDate.getValue());
  406. java.util.Calendar cal = fmt.getCalendar();
  407. return values.date(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH) + 1, cal.get(Calendar.DATE));
  408. } catch (IllegalArgumentException iae) {
  409. throw RuntimeExceptionFactory.dateTimeParsingError("Cannot parse input date: " + inputDate.getValue() +
  410. " using format string: " + formatString.getValue(), null, null);
  411. } catch (ParseException e) {
  412. throw RuntimeExceptionFactory.dateTimeParsingError("Cannot parse input date: " + inputDate.getValue() +
  413. " using format string: " + formatString.getValue(), null, null);
  414. }
  415. }
  416. public IValue parseDateInLocale(IString inputDate, IString formatString, IString locale)
  417. //@doc{Parse an input date given as a string using a specific locale and format string}
  418. {
  419. try {
  420. java.text.SimpleDateFormat fmt = new java.text.SimpleDateFormat(formatString.getValue(), new Locale(locale.getValue()));
  421. fmt.parse(inputDate.getValue());
  422. java.util.Calendar cal = fmt.getCalendar();
  423. return values.date(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH) + 1, cal.get(Calendar.DATE));
  424. } catch (IllegalArgumentException iae) {
  425. throw RuntimeExceptionFactory.dateTimeParsingError("Cannot parse input date: " + inputDate.getValue() +
  426. " using format string: " + formatString.getValue() + " in locale: " + locale.getValue(), null, null);
  427. } catch (ParseException e) {
  428. throw RuntimeExceptionFactory.dateTimeParsingError("Cannot parse input date: " + inputDate.getValue() +
  429. " using format string: " + formatString.getValue() + " in locale: " + locale.getValue(), null, null);
  430. }
  431. }
  432. public IValue parseTime(IString inputTime, IString formatString)
  433. //@doc{Parse an input time given as a string using the given format string}
  434. {
  435. try {
  436. java.text.SimpleDateFormat fmt = new java.text.SimpleDateFormat(formatString.getValue());
  437. fmt.parse(inputTime.getValue());
  438. java.util.Calendar cal = fmt.getCalendar();
  439. // The value for zone offset comes back in milliseconds. The number of
  440. // hours is thus milliseconds / 1000 (to get to seconds) / 60 (to get to minutes)
  441. // / 60 (to get to hours). Minutes is this except for the last division,
  442. // but then we use mod 60 since this gives us total # of minutes, including
  443. // the hours we have already computed.
  444. int zoneHours = cal.get(Calendar.ZONE_OFFSET) / (1000 * 60 * 60);
  445. int zoneMinutes = (cal.get(Calendar.ZONE_OFFSET) / (1000 * 60)) % 60;
  446. return values.time(cal.get(Calendar.HOUR_OF_DAY), cal.get(Calendar.MINUTE), cal.get(Calendar.SECOND), cal.get(Calendar.MILLISECOND), zoneHours, zoneMinutes);
  447. } catch (IllegalArgumentException iae) {
  448. throw RuntimeExceptionFactory.dateTimeParsingError("Cannot parse input date: " + inputTime.getValue() +
  449. " using format string: " + formatString.getValue(), null, null);
  450. } catch (ParseException e) {
  451. throw RuntimeExceptionFactory.dateTimeParsingError("Cannot parse input date: " + inputTime.getValue() +
  452. " using format string: " + formatString.getValue(), null, null);
  453. }
  454. }
  455. public IValue parseTimeInLocale(IString inputTime, IString formatString, IString locale)
  456. //@doc{Parse an input time given as a string using a specific locale and format string}
  457. {
  458. try {
  459. java.text.SimpleDateFormat fmt = new java.text.SimpleDateFormat(formatString.getValue(), new Locale(locale.getValue()));
  460. fmt.parse(inputTime.getValue());
  461. java.util.Calendar cal = fmt.getCalendar();
  462. // The value for zone offset comes back in milliseconds. The number of
  463. // hours is thus milliseconds / 1000 (to get to seconds) / 60 (to get to minutes)
  464. // / 60 (to get to hours). Minutes is this except for the last division,
  465. // but then we use mod 60 since this gives us total # of minutes, including
  466. // the hours we have already computed.
  467. int zoneHours = cal.get(Calendar.ZONE_OFFSET) / (1000 * 60 * 60);
  468. int zoneMinutes = (cal.get(Calendar.ZONE_OFFSET) / (1000 * 60)) % 60;
  469. return values.time(cal.get(Calendar.HOUR_OF_DAY), cal.get(Calendar.MINUTE), cal.get(Calendar.SECOND), cal.get(Calendar.MILLISECOND), zoneHours, zoneMinutes);
  470. } catch (IllegalArgumentException iae) {
  471. throw RuntimeExceptionFactory.dateTimeParsingError("Cannot parse input time: " + inputTime.getValue() +
  472. " using format string: " + formatString.getValue() + " in locale: " + locale.getValue(), null, null);
  473. } catch (ParseException e) {
  474. throw RuntimeExceptionFactory.dateTimeParsingError("Cannot parse input time: " + inputTime.getValue() +
  475. " using format string: " + formatString.getValue() + " in locale: " + locale.getValue(), null, null);
  476. }
  477. }
  478. public IValue parseDateTime(IString inputDateTime, IString formatString)
  479. //@doc{Parse an input datetime given as a string using the given format string}
  480. {
  481. try {
  482. java.text.SimpleDateFormat fmt = new java.text.SimpleDateFormat(formatString.getValue());
  483. fmt.setLenient(false);
  484. fmt.parse(inputDateTime.getValue());
  485. java.util.Calendar cal = fmt.getCalendar();
  486. int zoneHours = cal.get(Calendar.ZONE_OFFSET) / (1000 * 60 * 60);
  487. int zoneMinutes = (cal.get(Calendar.ZONE_OFFSET) / (1000 * 60)) % 60;
  488. return values.datetime(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH) + 1, cal.get(Calendar.DAY_OF_MONTH), cal.get(Calendar.HOUR_OF_DAY), cal.get(Calendar.MINUTE), cal.get(Calendar.SECOND), cal.get(Calendar.MILLISECOND), zoneHours, zoneMinutes);
  489. } catch (IllegalArgumentException iae) {
  490. throw RuntimeExceptionFactory.dateTimeParsingError("Cannot parse input datetime: " + inputDateTime.getValue() +
  491. " using format string: " + formatString.getValue(), null, null);
  492. } catch (ParseException e) {
  493. throw RuntimeExceptionFactory.dateTimeParsingError("Cannot parse input datetime: " + inputDateTime.getValue() +
  494. " using format string: " + formatString.getValue(), null, null);
  495. }
  496. }
  497. public IValue parseDateTimeInLocale(IString inputDateTime, IString formatString, IString locale)
  498. //@doc{Parse an input datetime given as a string using a specific locale and format string}
  499. {
  500. try {
  501. java.text.SimpleDateFormat fmt = new java.text.SimpleDateFormat(formatString.getValue(), new Locale(locale.getValue()));
  502. fmt.parse(inputDateTime.getValue());
  503. java.util.Calendar cal = fmt.getCalendar();
  504. int zoneHours = cal.get(Calendar.ZONE_OFFSET) / (1000 * 60 * 60);
  505. int zoneMinutes = (cal.get(Calendar.ZONE_OFFSET) / (1000 * 60)) % 60;
  506. return values.datetime(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH) + 1, cal.get(Calendar.DAY_OF_MONTH), cal.get(Calendar.HOUR_OF_DAY), cal.get(Calendar.MINUTE), cal.get(Calendar.SECOND), cal.get(Calendar.MILLISECOND), zoneHours, zoneMinutes);
  507. } catch (IllegalArgumentException iae) {
  508. throw RuntimeExceptionFactory.dateTimeParsingError("Cannot parse input datetime: " + inputDateTime.getValue() +
  509. " using format string: " + formatString.getValue() + " in locale: " + locale.getValue(), null, null);
  510. } catch (ParseException e) {
  511. throw RuntimeExceptionFactory.dateTimeParsingError("Cannot parse input datetime: " + inputDateTime.getValue() +
  512. " using format string: " + formatString.getValue() + " in locale: " + locale.getValue(), null, null);
  513. }
  514. }
  515. private Calendar getCalendarForDate(IDateTime inputDate) {
  516. if (inputDate.isDate() || inputDate.isDateTime()) {
  517. Calendar cal = Calendar.getInstance(TimeZone.getDefault(),Locale.getDefault());
  518. cal.setLenient(false);
  519. cal.set(inputDate.getYear(), inputDate.getMonthOfYear()-1, inputDate.getDayOfMonth());
  520. return cal;
  521. } else {
  522. throw new IllegalArgumentException("Cannot get date for a datetime that only represents the time");
  523. }
  524. }
  525. private Calendar getCalendarForTime(IDateTime inputTime) {
  526. if (inputTime.isTime() || inputTime.isDateTime()) {
  527. Calendar cal = Calendar.getInstance(TimeZone.getTimeZone(getTZString(inputTime.getTimezoneOffsetHours(),inputTime.getTimezoneOffsetMinutes())),Locale.getDefault());
  528. cal.setLenient(false);
  529. cal.set(Calendar.HOUR_OF_DAY, inputTime.getHourOfDay());
  530. cal.set(Calendar.MINUTE, inputTime.getMinuteOfHour());
  531. cal.set(Calendar.SECOND, inputTime.getSecondOfMinute());
  532. cal.set(Calendar.MILLISECOND, inputTime.getMillisecondsOfSecond());
  533. return cal;
  534. } else {
  535. throw new IllegalArgumentException("Cannot get time for a datetime that only represents the date");
  536. }
  537. }
  538. private Calendar getCalendarForDateTime(IDateTime inputDateTime) {
  539. if (inputDateTime.isDateTime()) {
  540. Calendar cal = Calendar.getInstance(TimeZone.getTimeZone(getTZString(inputDateTime.getTimezoneOffsetHours(),inputDateTime.getTimezoneOffsetMinutes())),Locale.getDefault());
  541. cal.setLenient(false);
  542. cal.set(inputDateTime.getYear(), inputDateTime.getMonthOfYear()-1, inputDateTime.getDayOfMonth(), inputDateTime.getHourOfDay(), inputDateTime.getMinuteOfHour(), inputDateTime.getSecondOfMinute());
  543. cal.set(Calendar.MILLISECOND, inputDateTime.getMillisecondsOfSecond());
  544. return cal;
  545. } else {
  546. throw new IllegalArgumentException("Cannot get date and time for a datetime that only represents the date or the time");
  547. }
  548. }
  549. public IValue printDate(IDateTime inputDate, IString formatString)
  550. //@doc{Print an input date using the given format string}
  551. {
  552. try {
  553. SimpleDateFormat sd = new SimpleDateFormat(formatString.getValue());
  554. Calendar cal = getCalendarForDate(inputDate);
  555. sd.setCalendar(cal);
  556. return values.string(sd.format(cal.getTime()));
  557. } catch (IllegalArgumentException iae) {
  558. throw RuntimeExceptionFactory.dateTimePrintingError("Cannot print time with format " + formatString.getValue(), null, null);
  559. }
  560. }
  561. public IValue printDate(IDateTime inputDate)
  562. //@doc{Print an input date using a default format string}
  563. {
  564. SimpleDateFormat sd = new SimpleDateFormat("yyyy-MM-dd");
  565. Calendar cal = getCalendarForDate(inputDate);
  566. sd.setCalendar(cal);
  567. return values.string(sd.format(cal.getTime()));
  568. }
  569. public IValue printDateInLocale(IDateTime inputDate, IString formatString, IString locale)
  570. //@doc{Print an input date using a specific locale and format string}
  571. {
  572. try {
  573. SimpleDateFormat sd = new SimpleDateFormat(formatString.getValue(),new ULocale(locale.getValue()));
  574. Calendar cal = getCalendarForDate(inputDate);
  575. sd.setCalendar(cal);
  576. return values.string(sd.format(cal.getTime()));
  577. } catch (IllegalArgumentException iae) {
  578. throw RuntimeExceptionFactory.dateTimePrintingError("Cannot print time with format " + formatString.getValue() + ", in locale: " + locale.getValue(), null, null);
  579. }
  580. }
  581. public IValue printDateInLocale(IDateTime inputDate, IString locale)
  582. //@doc{Print an input date using a specific locale and a default format string}
  583. {
  584. try {
  585. SimpleDateFormat sd = new SimpleDateFormat("yyyy-MM-dd",new ULocale(locale.getValue()));
  586. Calendar cal = getCalendarForDate(inputDate);
  587. sd.setCalendar(cal);
  588. return values.string(sd.format(cal.getTime()));
  589. } catch (IllegalArgumentException iae) {
  590. throw RuntimeExceptionFactory.dateTimePrintingError("Cannot print time in locale: " + locale.getValue(), null, null);
  591. }
  592. }
  593. public IValue printTime(IDateTime inputTime, IString formatString)
  594. //@doc{Print an input time using the given format string}
  595. {
  596. try {
  597. SimpleDateFormat sd = new SimpleDateFormat(formatString.getValue());
  598. Calendar cal = getCalendarForTime(inputTime);
  599. sd.setCalendar(cal);
  600. return values.string(sd.format(cal.getTime()));
  601. } catch (IllegalArgumentException iae) {
  602. throw RuntimeExceptionFactory.dateTimePrintingError("Cannot print time with format: " + formatString.getValue(), null, null);
  603. }
  604. }
  605. public IValue printTime(IDateTime inputTime)
  606. //@doc{Print an input time using a default format string}
  607. {
  608. SimpleDateFormat sd = new SimpleDateFormat("HH:mm:ss.SSSZ");
  609. Calendar cal = getCalendarForTime(inputTime);
  610. sd.setCalendar(cal);
  611. return values.string(sd.format(cal.getTime()));
  612. }
  613. public IValue printTimeInLocale(IDateTime inputTime, IString formatString, IString locale)
  614. //@doc{Print an input time using a specific locale and format string}
  615. {
  616. try {
  617. SimpleDateFormat sd = new SimpleDateFormat(formatString.getValue(),new ULocale(locale.getValue()));
  618. Calendar cal = getCalendarForTime(inputTime);
  619. sd.setCalendar(cal);
  620. return values.string(sd.format(cal.getTime()));
  621. } catch (IllegalArgumentException iae) {
  622. throw RuntimeExceptionFactory.dateTimePrintingError("Cannot print time in locale: " + locale.getValue(), null, null);
  623. }
  624. }
  625. public IValue printTimeInLocale(IDateTime inputTime, IString locale)
  626. //@doc{Print an input time using a specific locale and a default format string}
  627. {
  628. try {
  629. SimpleDateFormat sd = new SimpleDateFormat("HH:mm:ss.SSSZ",new ULocale(locale.getValue()));
  630. Calendar cal = getCalendarForTime(inputTime);
  631. sd.setCalendar(cal);
  632. return values.string(sd.format(cal.getTime()));
  633. } catch (IllegalArgumentException iae) {
  634. throw RuntimeExceptionFactory.dateTimePrintingError("Cannot print time in locale: " + locale.getValue(), null, null);
  635. }
  636. }
  637. public IValue printDateTime(IDateTime inputDateTime, IString formatString)
  638. //@doc{Print an input datetime using the given format string}
  639. {
  640. try {
  641. SimpleDateFormat sd = new SimpleDateFormat(formatString.getValue());
  642. Calendar cal = getCalendarForDateTime(inputDateTime);
  643. sd.setCalendar(cal);
  644. return values.string(sd.format(cal.getTime()));
  645. } catch (IllegalArgumentException iae) {
  646. throw RuntimeExceptionFactory.dateTimePrintingError("Cannot print datetime using format string: " + formatString.getValue(), null, null);
  647. }
  648. }
  649. public IValue printDateTime(IDateTime inputDateTime)
  650. //@doc{Print an input datetime using a default format string}
  651. {
  652. SimpleDateFormat sd = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSSZ");
  653. Calendar cal = getCalendarForDateTime(inputDateTime);
  654. sd.setCalendar(cal);
  655. return values.string(sd.format(cal.getTime()));
  656. }
  657. public IValue printDateTimeInLocale(IDateTime inputDateTime, IString formatString, IString locale)
  658. //@doc{Print an input datetime using a specific locale and format string}
  659. {
  660. try {
  661. SimpleDateFormat sd = new SimpleDateFormat(formatString.getValue(),new ULocale(locale.getValue()));
  662. Calendar cal = getCalendarForDateTime(inputDateTime);
  663. sd.setCalendar(cal);
  664. return values.string(sd.format(cal.getTime()));
  665. } catch (IllegalArgumentException iae) {
  666. throw RuntimeExceptionFactory.dateTimePrintingError("Cannot print datetime using format string: " + formatString.getValue() +
  667. " in locale: " + locale.getValue(), null, null);
  668. }
  669. }
  670. public IValue printDateTimeInLocale(IDateTime inputDateTime, IString locale)
  671. //@doc{Print an input datetime using a specific locale and a default format string}
  672. {
  673. try {
  674. SimpleDateFormat sd = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSSZ",new ULocale(locale.getValue()));
  675. Calendar cal = getCalendarForDateTime(inputDateTime);
  676. sd.setCalendar(cal);
  677. return values.string(sd.format(cal.getTime()));
  678. } catch (IllegalArgumentException iae) {
  679. throw RuntimeExceptionFactory.dateTimePrintingError("Cannot print datetime in locale: " + locale.getValue(), null, null);
  680. }
  681. }
  682. /*
  683. * Graph
  684. */
  685. private HashMap<IValue,Distance> distance;
  686. private HashMap<IValue, IValue> pred;
  687. private HashSet<IValue> settled;
  688. private PriorityQueue<IValue> Q;
  689. private int MAXDISTANCE = 10000;
  690. private HashMap<IValue, LinkedList<IValue>> adjacencyList;
  691. private void buildAdjacencyListAndDistance(IRelation G){
  692. adjacencyList = new HashMap<IValue, LinkedList<IValue>> ();
  693. distance = new HashMap<IValue, Distance>();
  694. for(IValue v : G){
  695. ITuple tup = (ITuple) v;
  696. IValue from = tup.get(0);
  697. IValue to = tup.get(1);
  698. if(distance.get(from) == null)
  699. distance.put(from, new Distance(MAXDISTANCE));
  700. if(distance.get(to) == null)
  701. distance.put(to, new Distance(MAXDISTANCE));
  702. LinkedList<IValue> adjacencies = adjacencyList.get(from);
  703. if(adjacencies == null)
  704. adjacencies = new LinkedList<IValue>();
  705. adjacencies.add(to);
  706. adjacencyList.put(from, adjacencies);
  707. }
  708. }
  709. public IValue shortestPathPair(IRelation G, IValue From, IValue To){
  710. buildAdjacencyListAndDistance(G);
  711. distance.put(From, new Distance(0));
  712. pred = new HashMap<IValue, IValue>();
  713. settled = new HashSet<IValue>();
  714. Q = new PriorityQueue<IValue>(G.size(), new NodeComparator(distance));
  715. Q.add(From);
  716. while(!Q.isEmpty()){
  717. IValue u = Q.remove();
  718. if(u.isEqual(To))
  719. return extractPath(From, u);
  720. settled.add(u);
  721. relaxNeighbours(u);
  722. }
  723. return values.list();
  724. }
  725. private void relaxNeighbours(IValue u){
  726. LinkedList<IValue> adjacencies = adjacencyList.get(u);
  727. if(adjacencies != null) {
  728. for(IValue v : adjacencyList.get(u)){
  729. if(!settled.contains(v)){
  730. Distance dv = distance.get(v);
  731. Distance du = distance.get(u);
  732. if(dv.intval > du.intval + 1){ // 1 is default weight of each edge
  733. dv.intval = du.intval + 1;
  734. pred.put(v,u);
  735. Q.add(v);
  736. }
  737. }
  738. }
  739. }
  740. }
  741. private IList extractPath(IValue start, IValue u){
  742. Type listType = types.listType(start.getType());
  743. IListWriter w = listType.writer(values);
  744. if(!start.isEqual(u)){
  745. w.insert(u);
  746. while(!pred.get(u).isEqual(start)){
  747. u = pred.get(u);
  748. w.insert(u);
  749. }
  750. // TODO Check if a path was found at all; it could be that we just hit the root of the graph.
  751. }
  752. w.insert(start);
  753. return w.done();
  754. }
  755. public void print(IValue arg, IEvaluatorContext eval){
  756. PrintWriter currentOutStream = eval.getStdOut();
  757. try{
  758. if(arg.getType().isStringType()){
  759. currentOutStream.print(((IString) arg).getValue().toString());
  760. }
  761. else if(arg.getType().isSubtypeOf(Factory.Tree)){
  762. currentOutStream.print(TreeAdapter.yield((IConstructor) arg));
  763. }
  764. else if (arg.getType().isSubtypeOf(Factory.Type)) {
  765. currentOutStream.print(SymbolAdapter.toString((IConstructor) ((IConstructor) arg).get("symbol")));
  766. }
  767. else{
  768. currentOutStream.print(arg.toString());
  769. }
  770. }finally{
  771. currentOutStream.flush();
  772. }
  773. }
  774. public void iprint(IValue arg, IEvaluatorContext eval){
  775. StandardTextWriter w = new StandardTextWriter(true, 2);
  776. try {
  777. w.write(arg, eval.getStdOut());
  778. }
  779. catch (IOException e) {
  780. RuntimeExceptionFactory.io(values.string("Could not print indented value"), eval.getCurrentAST(), eval.getStackTrace());
  781. }
  782. finally{
  783. eval.getStdOut().flush();
  784. }
  785. }
  786. public void iprintln(IValue arg, IEvaluatorContext eval){
  787. StandardTextWriter w = new StandardTextWriter(true, 2);
  788. try {
  789. w.write(arg, eval.getStdOut());
  790. eval.getStdOut().println();
  791. }
  792. catch (IOException e) {
  793. RuntimeExceptionFactory.io(values.string("Could not print indented value"), eval.getCurrentAST(), eval.getStackTrace());
  794. }
  795. finally{
  796. eval.getStdOut().flush();
  797. }
  798. }
  799. public void println(IEvaluatorContext eval) {
  800. eval.getStdOut().println();
  801. eval.getStdOut().flush();
  802. }
  803. public void println(IValue arg, IEvaluatorContext eval){
  804. PrintWriter currentOutStream = eval.getStdOut();
  805. try{
  806. if(arg.getType().isStringType()){
  807. currentOutStream.print(((IString) arg).getValue());
  808. }
  809. else if(arg.getType().isSubtypeOf(Factory.Tree)){
  810. currentOutStream.print(TreeAdapter.yield((IConstructor) arg));
  811. }
  812. else if (arg.getType().isSubtypeOf(Factory.Type)) {
  813. currentOutStream.print(SymbolAdapter.toString((IConstructor) ((IConstructor) arg).get("symbol")));
  814. }
  815. else{
  816. currentOutStream.print(arg.toString());
  817. }
  818. currentOutStream.println();
  819. }finally{
  820. currentOutStream.flush();
  821. }
  822. }
  823. public void rprintln(IValue arg, IEvaluatorContext eval){
  824. PrintWriter currentOutStream = eval.getStdOut();
  825. try{
  826. currentOutStream.print(arg.toString());
  827. currentOutStream.println();
  828. }finally{
  829. currentOutStream.flush();
  830. }
  831. }
  832. public void rprint(IValue arg, IEvaluatorContext eval){
  833. PrintWriter currentOutStream = eval.getStdOut();
  834. try{
  835. currentOutStream.print(arg.toString());
  836. }finally{
  837. currentOutStream.flush();
  838. }
  839. }
  840. @Deprecated
  841. public IValue readFile(IString filename){
  842. IListWriter w = types.listType(types.stringType()).writer(values);
  843. BufferedReader in = null;
  844. try{
  845. in = new BufferedReader(new FileReader(filename.getValue()));
  846. java.lang.String line;
  847. do {
  848. line = in.readLine();
  849. if(line != null){
  850. w.append(values.string(line));
  851. }
  852. } while (line != null);
  853. }catch(FileNotFoundException fnfex){
  854. throw RuntimeExceptionFactory.pathNotFound(values.sourceLocation(filename.getValue()), null, null);
  855. }catch(IOException ioex){
  856. throw RuntimeExceptionFactory.io(values.string(ioex.getMessage()), null, null);
  857. }finally{
  858. if(in != null){
  859. try{
  860. in.close();
  861. }catch(IOException ioex){
  862. throw RuntimeExceptionFactory.io(values.string(ioex.getMessage()), null, null);
  863. }
  864. }
  865. }
  866. return w.done();
  867. }
  868. public IValue exists(ISourceLocation sloc, IEvaluatorContext ctx) {
  869. return values.bool(ctx.getResolverRegistry().exists(sloc.getURI()));
  870. }
  871. public IValue lastModified(ISourceLocation sloc, IEvaluatorContext ctx) {
  872. try {
  873. return values.datetime(ctx.getResolverRegistry().lastModified(sloc.getURI()));
  874. } catch(FileNotFoundException e){
  875. throw RuntimeExceptionFactory.pathNotFound(sloc, null, null);
  876. }
  877. catch (IOException e) {
  878. throw RuntimeExceptionFactory.io(values.string(e.getMessage()), ctx.getCurrentAST(), ctx.getStackTrace());
  879. }
  880. }
  881. public IValue isDirectory(ISourceLocation sloc, IEvaluatorContext ctx) {
  882. return values.bool(ctx.getResolverRegistry().isDirectory(sloc.getURI()));
  883. }
  884. public IValue isFile(ISourceLocation sloc, IEvaluatorContext ctx) {
  885. return values.bool(ctx.getResolverRegistry().isFile(sloc.getURI()));
  886. }
  887. public void mkDirectory(ISourceLocation sloc, IEvaluatorContext ctx) throws IOException {
  888. ctx.getResolverRegistry().mkDirectory(sloc.getURI());
  889. }
  890. public IValue listEntries(ISourceLocation sloc, IEvaluatorContext ctx) {
  891. try {
  892. java.lang.String [] entries = ctx.getResolverRegistry().listEntries(sloc.getURI());
  893. IListWriter w = values.listWriter(types.stringType());
  894. for(java.lang.String entry : entries){
  895. w.append(values.string(entry));
  896. }
  897. return w.done();
  898. } catch(FileNotFoundException e){
  899. throw RuntimeExceptionFactory.pathNotFound(sloc, ctx.getCurrentAST(), null);
  900. } catch (IOException e) {
  901. throw RuntimeExceptionFactory.io(values.string(e.getMessage()), ctx.getCurrentAST(), ctx.getStackTrace());
  902. }
  903. }
  904. public ISet charsets() {
  905. ISetWriter w = values.setWriter();
  906. for (String s : Charset.availableCharsets().keySet()) {
  907. w.insert(values.string(s));
  908. }
  909. return w.done();
  910. }
  911. public IValue readFile(ISourceLocation sloc, IEvaluatorContext ctx){
  912. try {
  913. Charset c = ctx.getResolverRegistry().getCharset(sloc.getURI());
  914. if (c != null)
  915. return readFileEnc(sloc, values.string(c.name()), ctx);
  916. return consumeInputStream(sloc, ctx.getResolverRegistry().getCharacterReader(sloc.getURI()), ctx);
  917. } catch(FileNotFoundException e){
  918. throw RuntimeExceptionFactory.pathNotFound(sloc, ctx.getCurrentAST(), null);
  919. }
  920. catch (IOException e) {
  921. throw RuntimeExceptionFactory.io(values.string(e.getMessage()), null, null);
  922. }
  923. }
  924. public IValue readFileEnc(ISourceLocation sloc, IString charset, IEvaluatorContext ctx){
  925. try {
  926. return consumeInputStream(sloc, ctx.getResolverRegistry().getCharacterReader(sloc.getURI(), charset.getValue()), ctx);
  927. } catch(FileNotFoundException e){
  928. throw RuntimeExceptionFactory.pathNotFound(sloc, ctx.getCurrentAST(), null);
  929. } catch (IOException e) {
  930. throw RuntimeExceptionFactory.io(values.string(e.getMessage()), null, null);
  931. }
  932. }
  933. private IValue consumeInputStream(ISourceLocation sloc, Reader in, IEvaluatorContext ctx) {
  934. StringBuilder result = new StringBuilder(1024 * 1024);
  935. try{
  936. char[] buf = new char[4096];
  937. int count;
  938. while((count = in.read(buf)) != -1) {
  939. result.append(new java.lang.String(buf, 0, count));
  940. }
  941. java.lang.String str = result.toString();
  942. if(sloc.hasOffsetLength() && sloc.getOffset() != -1){
  943. str = str.substring(sloc.getOffset(), sloc.getOffset() + sloc.getLength());
  944. }
  945. return values.string(str);
  946. }catch(FileNotFoundException fnfex){
  947. throw RuntimeExceptionFactory.pathNotFound(sloc, ctx.getCurrentAST(), null);
  948. }catch(IOException ioex){
  949. throw RuntimeExceptionFactory.io(values.string(ioex.getMessage()), ctx.getCurrentAST(), null);
  950. }finally{
  951. if(in != null){
  952. try{
  953. in.close();
  954. }catch(IOException ioex){
  955. throw RuntimeExceptionFactory.io(values.string(ioex.getMessage()), ctx.getCurrentAST(), null);
  956. }
  957. }
  958. }
  959. }
  960. public IValue md5HashFile(ISourceLocation sloc, IEvaluatorContext ctx){
  961. StringBuilder result = new StringBuilder(1024 * 1024);
  962. InputStream in = null;
  963. try{
  964. in = ctx.getResolverRegistry().getInputStream(sloc.getURI());
  965. MessageDigest md = MessageDigest.getInstance("MD5");
  966. in = new DigestInputStream(in, md);
  967. byte[] buf = new byte[4096];
  968. int count;
  969. while((count = in.read(buf)) != -1){
  970. result.append(new java.lang.String(buf, 0, count));
  971. }
  972. return values.string(new String(md.digest()));
  973. }catch(FileNotFoundException fnfex){
  974. throw RuntimeExceptionFactory.pathNotFound(sloc, ctx.getCurrentAST(), null);
  975. }catch(IOException ioex){
  976. throw RuntimeExceptionFactory.io(values.string(ioex.getMessage()), ctx.getCurrentAST(), null);
  977. } catch (NoSuchAlgorithmException e) {
  978. throw RuntimeExceptionFactory.io(values.string("Cannot load MD5 digest algorithm"), ctx.getCurrentAST(), null);
  979. }finally{
  980. if(in != null){
  981. try{
  982. in.close();
  983. }catch(IOException ioex){
  984. throw RuntimeExceptionFactory.io(values.string(ioex.getMessage()), ctx.getCurrentAST(), null);
  985. }
  986. }
  987. }
  988. }
  989. public void writeFile(ISourceLocation sloc, IList V, IEvaluatorContext ctx) {
  990. writeFile(sloc, V, false, ctx);
  991. }
  992. public void writeFileEnc(ISourceLocation sloc, IString charset, IList V, IEvaluatorContext ctx) {
  993. writeFileEnc(sloc, charset, V, false, ctx);
  994. }
  995. private void writeFile(ISourceLocation sloc, IList V, boolean append, IEvaluatorContext ctx){
  996. IString charset = values.string("UTF8");
  997. if (append) {
  998. // in case the file already has a encoding, we have to correctly append that.
  999. InputStream in = null;
  1000. Charset detected = null;
  1001. try {
  1002. detected = ctx.getResolverRegistry().getCharset(sloc.getURI());
  1003. if (detected == null) {
  1004. in = ctx.getResolverRegistry().getInputStream(sloc.getURI());
  1005. detected = UnicodeDetector.estimateCharset(in);
  1006. }
  1007. }catch(FileNotFoundException fnfex){
  1008. throw RuntimeExceptionFactory.pathNotFound(sloc, ctx.getCurrentAST(), null);
  1009. } catch (IOException e) {
  1010. throw RuntimeExceptionFactory.io(values.string(e.getMessage()), ctx.getCurrentAST(), null);
  1011. }
  1012. finally {
  1013. if (in != null) {
  1014. try {
  1015. in.close();
  1016. } catch (IOException e) {
  1017. throw RuntimeExceptionFactory.io(values.string(e.getMessage()), ctx.getCurrentAST(), null);
  1018. }
  1019. }
  1020. }
  1021. if (detected != null)
  1022. charset = values.string(detected.name());
  1023. else {
  1024. charset = values.string(Charset.defaultCharset().name());
  1025. }
  1026. }
  1027. writeFileEnc(sloc, charset, V, append, ctx);
  1028. }
  1029. public IBool canEncode(IString charset) {
  1030. return values.bool(Charset.forName(charset.getValue()).canEncode());
  1031. }
  1032. private void writeFileEnc(ISourceLocation sloc, IString charset, IList V, boolean append, IEvaluatorContext ctx){
  1033. OutputStreamWriter out = null;
  1034. if (!Charset.forName(charset.getValue()).canEncode()) {
  1035. throw RuntimeExceptionFactory.illegalArgument(charset, null, null);
  1036. }
  1037. try{
  1038. out = new UnicodeOutputStreamWriter(ctx.getResolverRegistry().getOutputStream(sloc.getURI(), append), charset.getValue(), append);
  1039. for(IValue elem : V){
  1040. if (elem.getType().isStringType()) {
  1041. out.append(((IString) elem).getValue());
  1042. }else if (elem.getType().isSubtypeOf(Factory.Tree)) {
  1043. out.append(TreeAdapter.yield((IConstructor) elem));
  1044. }else{
  1045. out.append(elem.toString());
  1046. }
  1047. }
  1048. }catch(FileNotFoundException fnfex){
  1049. throw RuntimeExceptionFactory.pathNotFound(sloc, ctx.getCurrentAST(), null);
  1050. }catch(IOException ioex){
  1051. throw RuntimeExceptionFactory.io(values.string(ioex.getMessage()), ctx.getCurrentAST(), null);
  1052. }finally{
  1053. if(out != null){
  1054. try{
  1055. out.close();
  1056. }catch(IOException ioex){
  1057. throw RuntimeExceptionFactory.io(values.string(ioex.getMessage()), ctx.getCurrentAST(), null);
  1058. }
  1059. }
  1060. }
  1061. return;
  1062. }
  1063. public void appendToFile(ISourceLocation sloc, IList V, IEvaluatorContext ctx){
  1064. writeFile(sloc, V, true, ctx);
  1065. }
  1066. public void appendToFileEnc(ISourceLocation sloc, IString charset, IList V, IEvaluatorContext ctx){
  1067. writeFileEnc(sloc, charset, V, true, ctx);
  1068. }
  1069. public IList readFileLines(ISourceLocation sloc, IEvaluatorContext ctx){
  1070. try {
  1071. Charset detected = ctx.getResolverRegistry().getCharset(sloc.getURI());
  1072. if (detected != null)
  1073. return readFileLinesEnc(sloc, values.string(detected.name()), ctx);
  1074. return consumeInputStreamLines(sloc, ctx.getResolverRegistry().getCharacterReader(sloc.getURI()), ctx);
  1075. }catch(MalformedURLException e){
  1076. throw RuntimeExceptionFactory.malformedURI(sloc.toString(), null, null);
  1077. }catch(FileNotFoundException e){
  1078. throw RuntimeExceptionFactory.pathNotFound(sloc, ctx.getCurrentAST(), null);
  1079. }catch(IOException e){
  1080. throw RuntimeExceptionFactory.io(values.string(e.getMessage()), ctx.getCurrentAST(), null);
  1081. }
  1082. }
  1083. public IList readFileLinesEnc(ISourceLocation sloc, IString charset, IEvaluatorContext ctx){
  1084. try {
  1085. return consumeInputStreamLines(sloc, ctx.getResolverRegistry().getCharacterReader(sloc.getURI(),charset.getValue()), ctx);
  1086. }catch(MalformedURLException e){
  1087. throw RuntimeExceptionFactory.malformedURI(sloc.toString(), null, null);
  1088. }catch(FileNotFoundException e){
  1089. throw RuntimeExceptionFactory.pathNotFound(sloc, ctx.getCurrentAST(), null);
  1090. }catch(IOException e){
  1091. throw RuntimeExceptionFactory.io(values.string(e.getMessage()), ctx.getCurrentAST(), null);
  1092. }
  1093. }
  1094. private IList consumeInputStreamLines(ISourceLocation sloc, Reader stream, IEvaluatorContext ctx ) {
  1095. IListWriter w = types.listType(types.stringType()).writer(values);
  1096. BufferedReader in = null;
  1097. try{
  1098. in = new BufferedReader(stream);
  1099. java.lang.String line;
  1100. int i = 0;
  1101. // int offset = sloc.getOffset();
  1102. int beginLine = sloc.hasLineColumn() ? sloc.getBeginLine() : -1;
  1103. int beginColumn = sloc.hasLineColumn() ? sloc.getBeginColumn() : -1;
  1104. int endLine = sloc.hasLineColumn() ? sloc.getEndLine() : -1;
  1105. int endColumn = sloc.hasLineColumn() ? sloc.getEndColumn() : -1;
  1106. do{
  1107. line = in.readLine();
  1108. i++;
  1109. if(line != null){
  1110. if(!sloc.hasOffsetLength()){
  1111. w.append(values.string(line));
  1112. }else{
  1113. if(!sloc.hasLineColumn()){
  1114. endColumn = line.length();
  1115. }
  1116. if(i == beginLine){
  1117. if(i == endLine){
  1118. w.append(values.string(line.substring(beginColumn, endColumn)));
  1119. }else{
  1120. w.append(values.string(line.substring(beginColumn)));
  1121. }
  1122. }else if(i > beginLine){
  1123. if(i == endLine){
  1124. w.append(values.string(line.substring(0, endColumn)));
  1125. }
  1126. else if(i < endLine){
  1127. w.append(values.string(line));
  1128. }
  1129. }
  1130. }
  1131. }
  1132. }while(line != null);
  1133. }catch(IOException e){
  1134. throw RuntimeExceptionFactory.io(values.string(e.getMessage()), ctx.getCurrentAST(), null);
  1135. }finally{
  1136. if(in != null){
  1137. try{
  1138. in.close();
  1139. }catch(IOException ioex){
  1140. throw RuntimeExceptionFactory.io(values.string(ioex.getMessage()), ctx.getCurrentAST(), null);
  1141. }
  1142. }
  1143. }
  1144. return w.done();
  1145. }
  1146. public IList readFileBytes(ISourceLocation sloc, IEvaluatorContext ctx){
  1147. IListWriter w = types.listType(types.integerType()).writer(values);
  1148. BufferedInputStream in = null;
  1149. try{
  1150. InputStream stream = ctx.getResolverRegistry().getInputStream(sloc.getURI());
  1151. in = new BufferedInputStream(stream);
  1152. int read;
  1153. final int size = 256;
  1154. byte bytes[] = new byte[size];
  1155. do{
  1156. read = in.read(bytes);
  1157. for (

Large files files are truncated, but you can click here to view the full file