<commit_before>/*
 *            Copyright 2009-2012 The VOTCA Development Team
 *                       (http://www.votca.org)
 *
 *      Licensed under the Apache License, Version 2.0 (the "License")
 *
 * You may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *              http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

#include <votca/ctp/qmapplication.h>
#include <votca/ctp/version.h>

namespace votca { namespace ctp {

QMApplication::QMApplication() {
    Calculatorfactory::RegisterAll();
}

void QMApplication::Initialize(void) {
    votca::csg::TrajectoryWriter::RegisterPlugins();
    votca::csg::TrajectoryReader::RegisterPlugins();

    Calculatorfactory::RegisterAll();

    namespace propt = boost::program_options;

    AddProgramOptions() ("options,o", propt::value<string>(),
        "  calculator options");
    AddProgramOptions() ("file,f", propt::value<string>(),
        "  sqlight state file, *.sql");
    AddProgramOptions() ("first-frame,i", propt::value<int>()->default_value(1),
        "  start from this frame");
    AddProgramOptions() ("nframes,n", propt::value<int>()->default_value(-1),
        "  number of frames to process");
    AddProgramOptions() ("nthreads,t", propt::value<int>()->default_value(1),
        "  number of threads to create");
    AddProgramOptions() ("save,s", propt::value<int>()->default_value(1),
        "  whether or not to save changes to state file");
    AddProgramOptions() ("restart,r", propt::value<string>()->default_value(""),
        "  parallelized job execution: job restart pattern; "
            "e.g. '-r host(mach1:1234,mach2:5678) stat(FAILED)'");
    AddProgramOptions() ("cache,c", propt::value<int>()->default_value(8),
        "  parallelized job execution: job cache size");
}

bool QMApplication::EvaluateOptions(void) {
    CheckRequired("options", "Please provide an xml file with calculator options");
    CheckRequired("file", "Please provide the state file");
    return true;
}

void QMApplication::Run() {

    load_property_from_xml(_options, _op_vm["options"].as<string>());

    // EVALUATE OPTIONS
    int nThreads = OptionsMap()["nthreads"].as<int>();
    int nframes = OptionsMap()["nframes"].as<int>();
    int fframe = OptionsMap()["first-frame"].as<int>();
    if (fframe-- == 0) throw runtime_error("ERROR: First frame is 0, counting "
                                           "in VOTCA::CTP starts from 1.");
    int  save = OptionsMap()["save"].as<int>();

    // STATESAVER & PROGRESS OBSERVER
    string statefile = OptionsMap()["file"].as<string>();
    StateSaverSQLite statsav;
    statsav.Open(_top, statefile);

    ProgObserver< vector<Job*>, Job*, Job::JobResult > progObs
        = ProgObserver< vector<Job*>, Job*, Job::JobResult >();
    progObs.InitCmdLineOpts(OptionsMap());

    // INITIALIZE & RUN CALCULATORS
    cout << "Initializing calculators " << endl;
    BeginEvaluate(nThreads, &progObs);

    while (statsav.NextFrame()) {
        cout << "Evaluating frame " << _top.getDatabaseId() << endl;
        EvaluateFrame();
        if (save == 1) { statsav.WriteFrame(); }
        else { cout << "Changes have not been written to state file." << endl; }
    }
    statsav.Close();
    EndEvaluate();

}

void QMApplication::AddCalculator(QMCalculator* calculator) {
    _calculators.push_back(calculator);
}

void QMApplication::BeginEvaluate(int nThreads = 1,
        ProgObserver< vector<Job*>, Job*, Job::JobResult > *obs = NULL) {
    list< QMCalculator* > ::iterator it;
    for (it = _calculators.begin(); it != _calculators.end(); it++) {
        cout << "... " << (*it)->Identify() << " ";
        (*it)->setnThreads(nThreads);
        (*it)->setProgObserver(obs);
        (*it)->Initialize(&_top, &_options);
        cout << endl;
    }
}

bool QMApplication::EvaluateFrame() {
    list< QMCalculator* > ::iterator it;
    for (it = _calculators.begin(); it != _calculators.end(); it++) {
        cout << "... " << (*it)->Identify() << " " << flush;
        (*it)->EvaluateFrame(&_top);
        cout << endl;
    }
}

void QMApplication::EndEvaluate() {
    list< QMCalculator* > ::iterator it;
    for (it = _calculators.begin(); it != _calculators.end(); it++) {
        (*it)->EndEvaluate(&_top);
    }
}

void QMApplication::ShowHelpText(std::ostream &out) {
    string name = ProgramName();
    if (VersionString() != "") name = name + ", version " + VersionString();
    votca::ctp::HelpTextHeader(name);
    HelpText(out);
    out << "\n\n" << OptionsDesc() << endl;
}

}}
<commit_msg>Fixed firstFrame, nFrames handling.<commit_after>/*
 *            Copyright 2009-2012 The VOTCA Development Team
 *                       (http://www.votca.org)
 *
 *      Licensed under the Apache License, Version 2.0 (the "License")
 *
 * You may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *              http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

#include <votca/ctp/qmapplication.h>
#include <votca/ctp/version.h>

namespace votca { namespace ctp {

QMApplication::QMApplication() {
    Calculatorfactory::RegisterAll();
}

void QMApplication::Initialize(void) {
    votca::csg::TrajectoryWriter::RegisterPlugins();
    votca::csg::TrajectoryReader::RegisterPlugins();

    Calculatorfactory::RegisterAll();

    namespace propt = boost::program_options;

    AddProgramOptions() ("options,o", propt::value<string>(),
        "  calculator options");
    AddProgramOptions() ("file,f", propt::value<string>(),
        "  sqlight state file, *.sql");
    AddProgramOptions() ("first-frame,i", propt::value<int>()->default_value(1),
        "  start from this frame");
    AddProgramOptions() ("nframes,n", propt::value<int>()->default_value(1),
        "  number of frames to process");
    AddProgramOptions() ("nthreads,t", propt::value<int>()->default_value(1),
        "  number of threads to create");
    AddProgramOptions() ("save,s", propt::value<int>()->default_value(1),
        "  whether or not to save changes to state file");
    AddProgramOptions() ("restart,r", propt::value<string>()->default_value(""),
        "  parallelized job execution: job restart pattern; "
            "e.g. '-r host(mach1:1234,mach2:5678) stat(FAILED)'");
    AddProgramOptions() ("cache,c", propt::value<int>()->default_value(8),
        "  parallelized job execution: job cache size");
}

bool QMApplication::EvaluateOptions(void) {
    CheckRequired("options", "Please provide an xml file with calculator options");
    CheckRequired("file", "Please provide the state file");
    return true;
}

void QMApplication::Run() {

    load_property_from_xml(_options, _op_vm["options"].as<string>());

    // EVALUATE OPTIONS
    int nThreads = OptionsMap()["nthreads"].as<int>();
    int nframes = OptionsMap()["nframes"].as<int>();
    int fframe = OptionsMap()["first-frame"].as<int>();
    if (fframe-- == 0) throw runtime_error("ERROR: First frame is 0, counting "
                                           "in VOTCA::CTP starts from 1.");
    int  save = OptionsMap()["save"].as<int>();

    // STATESAVER & PROGRESS OBSERVER
    string statefile = OptionsMap()["file"].as<string>();
    StateSaverSQLite statsav;
    statsav.Open(_top, statefile);

    ProgObserver< vector<Job*>, Job*, Job::JobResult > progObs
        = ProgObserver< vector<Job*>, Job*, Job::JobResult >();
    progObs.InitCmdLineOpts(OptionsMap());

    // INITIALIZE & RUN CALCULATORS
    cout << "Initializing calculators " << endl;
    BeginEvaluate(nThreads, &progObs);

    int frameId = -1;
    int framesDone = 0;
    while (statsav.NextFrame() && framesDone < nframes) {
        frameId += 1;
        if (frameId < fframe) continue;
        cout << "Evaluating frame " << _top.getDatabaseId() << endl;
        EvaluateFrame();
        if (save == 1) { statsav.WriteFrame(); }
        else { cout << "Changes have not been written to state file." << endl; }
        framesDone += 1;
    }

    if (framesDone == 0)
        cout << "Input requires first frame = " << fframe+1 << ", # frames = "
             << nframes << " => No frames processed.";

    statsav.Close();
    EndEvaluate();

}

void QMApplication::AddCalculator(QMCalculator* calculator) {
    _calculators.push_back(calculator);
}

void QMApplication::BeginEvaluate(int nThreads = 1,
        ProgObserver< vector<Job*>, Job*, Job::JobResult > *obs = NULL) {
    list< QMCalculator* > ::iterator it;
    for (it = _calculators.begin(); it != _calculators.end(); it++) {
        cout << "... " << (*it)->Identify() << " ";
        (*it)->setnThreads(nThreads);
        (*it)->setProgObserver(obs);
        (*it)->Initialize(&_top, &_options);
        cout << endl;
    }
}

bool QMApplication::EvaluateFrame() {
    list< QMCalculator* > ::iterator it;
    for (it = _calculators.begin(); it != _calculators.end(); it++) {
        cout << "... " << (*it)->Identify() << " " << flush;
        (*it)->EvaluateFrame(&_top);
        cout << endl;
    }
}

void QMApplication::EndEvaluate() {
    list< QMCalculator* > ::iterator it;
    for (it = _calculators.begin(); it != _calculators.end(); it++) {
        (*it)->EndEvaluate(&_top);
    }
}

void QMApplication::ShowHelpText(std::ostream &out) {
    string name = ProgramName();
    if (VersionString() != "") name = name + ", version " + VersionString();
    votca::ctp::HelpTextHeader(name);
    HelpText(out);
    out << "\n\n" << OptionsDesc() << endl;
}

}}
<|endoftext|>


<commit_before>#ifdef __APPLE__

#include "WProgram.h"

#include <midi-common.hh>
#include <MidiUartParent.hh>
#include "MidiUartOSX.h"

void getMidiName(MIDIEndpointRef ep, char *buf, uint16_t len) {
		CFStringRef pname, pmanuf, pmodel;
		char name[64], manuf[64], model[64];

		MIDIObjectGetStringProperty(ep, kMIDIPropertyName, &pname);
		MIDIObjectGetStringProperty(ep, kMIDIPropertyManufacturer, &pmanuf);
		MIDIObjectGetStringProperty(ep, kMIDIPropertyModel, &pmodel);

		CFStringGetCString(pname, name, sizeof(name), 0);
		CFStringGetCString(pmanuf, manuf, sizeof(manuf), 0);
		CFStringGetCString(pmodel, model, sizeof(model), 0);
		CFRelease(pname);
		CFRelease(pmanuf);
		CFRelease(pmodel);

		snprintf(buf, len, "%s - %s", name, manuf);
}

void MidiUartOSXClass::listInputMidiDevices() {
	unsigned long   iNumDevs, i;

	iNumDevs = MIDIGetNumberOfSources();

	for (i = 0; i < iNumDevs; i++) {
		char buf[128];
		MIDIEndpointRef ep = MIDIGetSource(i);
		getMidiName(ep, buf, countof(buf));
		printf("%ld) %s\n", i, buf);
	}
}

void MidiUartOSXClass::listOutputMidiDevices() {
	unsigned long   iNumDevs, i;

	iNumDevs = MIDIGetNumberOfDestinations();

	for (i = 0; i < iNumDevs; i++) {
		char buf[128];
		MIDIEndpointRef ep = MIDIGetDestination(i);
		getMidiName(ep, buf, countof(buf));
		printf("%ld) %s\n", i, buf);
	}
}

MidiUartOSXClass::MidiUartOSXClass(int _inputDevice, int _outputDevice) {
  inputDevice = -1;
  outputDevice = -1;
  outPort = NULL;
  dest = NULL;
  client = NULL;
  inPort = NULL;
  src = NULL;

  if ((_inputDevice >= 0) && (_outputDevice >= 0)) {
    init(_inputDevice, _outputDevice);
  }
}

static void midiReadProc(const MIDIPacketList *pktlist, void *refCon, void *connRefCon) {
  MidiUartOSXClass *uart = (MidiUartOSXClass *)refCon;
  if (uart != NULL) {
    if (uart->outPort != NULL && uart->dest != NULL) {
      MIDIPacket *packet = (MIDIPacket *)pktlist->packet;
      unsigned int j;
      int i;
      for (j = 0; j < pktlist->numPackets; j++) {
				for (i = 0; i < packet->length; i++) {
					uart->rxRb.put(packet->data[i]);
				}

	packet = MIDIPacketNext(packet);
      }
    }
  }
}

static void midiSysexSent(MIDISysexSendRequest *request) {
  printf("refcon : %p\n", request->completionRefCon);
  free(request);
}

void MidiUartOSXClass::init(int _inputDevice, int _outputDevice) {
  if ((inputDevice >= 0) || (outputDevice >= 0)) {
    fprintf(stderr, "MIDI ports already open\n");
    return;
  }

	MidiUartHostParent::init(_inputDevice, _outputDevice);

  inputDevice = _inputDevice;
  outputDevice = _outputDevice;
  MIDIClientCreate(CFSTR("MIDI Send"), NULL, NULL, &client);
  MIDIOutputPortCreate(client, CFSTR("Output port"), &outPort);
	char buf[128];
  dest = MIDIGetDestination(outputDevice);
	getMidiName(dest, buf, countof(buf));
	printf("opening output device  \"%s\"\n", buf);
  MIDIInputPortCreate(client, CFSTR("Input port"), midiReadProc, this, &inPort);
  src = MIDIGetSource(inputDevice);
	getMidiName(src, buf, countof(buf));
	printf("opening input device:  \"%s\"\n", buf);
  MIDIPortConnectSource(inPort, src, NULL);
}

void MidiUartOSXClass::midiSendLong(unsigned char *buf, unsigned long len) {
  struct MIDISysexSendRequest *sysexReq = (struct MIDISysexSendRequest *)malloc(sizeof(struct MIDISysexSendRequest) + len);

  sysexReq->destination = dest;
  sysexReq->data = ((unsigned char *)sysexReq) + sizeof(struct MIDISysexSendRequest);
  memcpy((void *)sysexReq->data, buf, len);
  sysexReq->bytesToSend = len;
  sysexReq->complete = false;
  sysexReq->completionProc = midiSysexSent;
  sysexReq->completionRefCon = this;
  MIDISendSysex(sysexReq);
}

void MidiUartOSXClass::midiSendShort(unsigned char status,
																		 unsigned char byte1,
																		 unsigned char byte2) {
  static struct MIDIPacketList pktlist;

  pktlist.numPackets = 1;
  pktlist.packet[0].timeStamp = 0;
  pktlist.packet[0].length = 3;
  pktlist.packet[0].data[0] = status;
  pktlist.packet[0].data[1] = byte1;
  pktlist.packet[0].data[2] = byte2;
  MIDISend(outPort, dest, &pktlist);
}

void MidiUartOSXClass::runLoop() {
  CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, true);
}

#endif /* __APPLE__ */
<commit_msg>Indentation<commit_after>#ifdef __APPLE__

#include "WProgram.h"

#include <midi-common.hh>
#include <MidiUartParent.hh>
#include "MidiUartOSX.h"

void getMidiName(MIDIEndpointRef ep, char *buf, uint16_t len) {
  CFStringRef pname, pmanuf, pmodel;
  char name[64], manuf[64], model[64];

  MIDIObjectGetStringProperty(ep, kMIDIPropertyName, &pname);
  MIDIObjectGetStringProperty(ep, kMIDIPropertyManufacturer, &pmanuf);
  MIDIObjectGetStringProperty(ep, kMIDIPropertyModel, &pmodel);

  CFStringGetCString(pname, name, sizeof(name), 0);
  CFStringGetCString(pmanuf, manuf, sizeof(manuf), 0);
  CFStringGetCString(pmodel, model, sizeof(model), 0);
  CFRelease(pname);
  CFRelease(pmanuf);
  CFRelease(pmodel);

  snprintf(buf, len, "%s - %s", name, manuf);
}

void MidiUartOSXClass::listInputMidiDevices() {
  unsigned long   iNumDevs, i;

  iNumDevs = MIDIGetNumberOfSources();

  for (i = 0; i < iNumDevs; i++) {
    char buf[128];
    MIDIEndpointRef ep = MIDIGetSource(i);
    getMidiName(ep, buf, countof(buf));
    printf("%ld) %s\n", i, buf);
  }
}

void MidiUartOSXClass::listOutputMidiDevices() {
  unsigned long   iNumDevs, i;

  iNumDevs = MIDIGetNumberOfDestinations();

  for (i = 0; i < iNumDevs; i++) {
    char buf[128];
    MIDIEndpointRef ep = MIDIGetDestination(i);
    getMidiName(ep, buf, countof(buf));
    printf("%ld) %s\n", i, buf);
  }
}

MidiUartOSXClass::MidiUartOSXClass(int _inputDevice, int _outputDevice) {
  inputDevice = -1;
  outputDevice = -1;
  outPort = NULL;
  dest = NULL;
  client = NULL;
  inPort = NULL;
  src = NULL;

  if ((_inputDevice >= 0) && (_outputDevice >= 0)) {
    init(_inputDevice, _outputDevice);
  }
}

static void midiReadProc(const MIDIPacketList *pktlist, void *refCon, void *connRefCon) {
  MidiUartOSXClass *uart = (MidiUartOSXClass *)refCon;
  if (uart != NULL) {
    if ((uart->outPort != 0) && (uart->dest != 0)) {
      MIDIPacket *packet = (MIDIPacket *)pktlist->packet;
      unsigned int j;
      int i;
      for (j = 0; j < pktlist->numPackets; j++) {
        for (i = 0; i < packet->length; i++) {
          uart->rxRb.put(packet->data[i]);
        }

	packet = MIDIPacketNext(packet);
      }
    }
  }
}

static void midiSysexSent(MIDISysexSendRequest *request) {
  printf("refcon : %p\n", request->completionRefCon);
  free(request);
}

void MidiUartOSXClass::init(int _inputDevice, int _outputDevice) {
  if ((inputDevice >= 0) || (outputDevice >= 0)) {
    fprintf(stderr, "MIDI ports already open\n");
    return;
  }

  MidiUartHostParent::init(_inputDevice, _outputDevice);

  inputDevice = _inputDevice;
  outputDevice = _outputDevice;
  MIDIClientCreate(CFSTR("MIDI Send"), NULL, NULL, &client);
  MIDIOutputPortCreate(client, CFSTR("Output port"), &outPort);
  char buf[128];
  dest = MIDIGetDestination(outputDevice);
  getMidiName(dest, buf, countof(buf));
  printf("opening output device  \"%s\"\n", buf);
  MIDIInputPortCreate(client, CFSTR("Input port"), midiReadProc, this, &inPort);
  src = MIDIGetSource(inputDevice);
  getMidiName(src, buf, countof(buf));
  printf("opening input device:  \"%s\"\n", buf);
  MIDIPortConnectSource(inPort, src, NULL);
}

void MidiUartOSXClass::midiSendLong(unsigned char *buf, unsigned long len) {
  struct MIDISysexSendRequest *sysexReq = (struct MIDISysexSendRequest *)malloc(sizeof(struct MIDISysexSendRequest) + len);

  sysexReq->destination = dest;
  sysexReq->data = ((unsigned char *)sysexReq) + sizeof(struct MIDISysexSendRequest);
  memcpy((void *)sysexReq->data, buf, len);
  sysexReq->bytesToSend = len;
  sysexReq->complete = false;
  sysexReq->completionProc = midiSysexSent;
  sysexReq->completionRefCon = this;
  MIDISendSysex(sysexReq);
}

void MidiUartOSXClass::midiSendShort(unsigned char status,
                                     unsigned char byte1,
                                     unsigned char byte2) {
  static struct MIDIPacketList pktlist;

  pktlist.numPackets = 1;
  pktlist.packet[0].timeStamp = 0;
  pktlist.packet[0].length = 3;
  pktlist.packet[0].data[0] = status;
  pktlist.packet[0].data[1] = byte1;
  pktlist.packet[0].data[2] = byte2;
  MIDISend(outPort, dest, &pktlist);
}

void MidiUartOSXClass::runLoop() {
  CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, true);
}

#endif /* __APPLE__ */
<|endoftext|>


<commit_before>#include "myHeader.h"
#include <iostream>
#include <fstream>
#include <string>
#include <iomanip>
using namespace std;

void printStringArr(const string a[], int n, ostream &os) {
	for (int i = 0; i < n; i++)
		os << "\n" << a[i];
}

int getIntInRange(int start, int end) {
	int x = getInt();

	while (x < start || x > end) {
		cout
			<< "\a\tYour number must be "
			<< (x < start ? "greater" : "less")
			<< " than or equal to "
			<< (x < start ? start : end)
			<< ". \n\tTry again: ";
		x = getInt();
	}

	return x;
}

int getInt() {
	double x = getNum();

	while (int(x) != x) {
		cout << "\a\tYour number is not an integer! \n\tTry Again: ";
		x = getNum();
	}

	return int(x);
}

double getNum() {
	double x;

	while (!(cin >> x)) {
		cin.clear();	cin.ignore(30, '\n');
		cout << "\a\tPlease no inapropriate characters! \n\tTry again: ";
	}
	cin.ignore(80, '\n');

	return x;
}

void loadStringArrayFromFile(string a[], int n, ifstream &ifs, bool &isLoaded) {
	for (int i = 0; i < n; i++)
		getline(ifs, a[i]);

	isLoaded = true;
}

void loadStats(int &gamesPlayed, int whoWon[], double whoWonPercent[], double numMoves[], int n, ifstream &ifs, bool &isLoaded) {

	while (ifs.peek() < '0' || ifs.peek() > '9')
		ifs.ignore();
	ifs >> gamesPlayed;

	while (ifs.peek() < '0' || ifs.peek() > '9')
		ifs.ignore();
	for (int i = 0; i < n; i++)
		ifs >> whoWon[i];

	while (ifs.peek() < '0' || ifs.peek() > '9')
		ifs.ignore();
	for (int i = 0; i < n; i++) {
		ifs >> whoWonPercent[i];
		ifs.ignore();	// for discarding '%'
	}

	while (ifs.peek() < '0' || ifs.peek() > '9')
		ifs.ignore();
	for (int i = 0; i < n; i++)
		ifs >> numMoves[i];

	isLoaded = true;
}

void printStats(int gamesPld, const int whoWon[], const double winPct[], const double numMvs[], int n, ostream &os) {

	os
		<< fixed << setprecision(1)
		<< "\nHunt the Wumpus Game Statistics"
		<< "\n\n\tGames Played: " << gamesPld
		<< "\n\n\tWho Won:"
		<< "\n\tPlayer\tWumpus\tPit\n";

	for (int i = 0; i < n; i++)
		os << "\t" << whoWon[i];

	os
		<< "\n\n\tWin Rate:"
		<< "\n\tPlayer\tWumpus\tPit\n";

	for (int i = 0; i < n; i++)
		os << "\t" << winPct[i] << "%";

	os
		<< "\n\n\tMoves per Game:"
		<< "\n\tLeast\tMost\tAverage\n"
		<< "\t" << int(numMvs[0])
		<< "\t" << int(numMvs[1])
		<< "\t" << numMvs[2];
}

void load2DArr(int map[][SIZE_EXITS], int const n, int const m) {
	int tempMap[21][3] = {
		{ 0, 0, 0 },		// room not actually used
		{ 2, 4, 19 },
		{ 1, 3, 6 },
		{ 2, 8, 20 },
		{ 1, 5, 9 },
		{ 4, 6, 11 },
		{ 2, 5, 7 },
		{ 6, 8, 12 },
		{ 3, 7, 13 },
		{ 4, 10, 16 },
		{ 9, 11, 14 },
		{ 5, 10, 12 },
		{ 7, 11, 15 },
		{ 8, 15, 18 },
		{ 10, 15, 17 },
		{ 12, 13, 14 },
		{ 9, 17, 19 },
		{ 14, 16, 18 },
		{ 13, 17, 20 },
		{ 1, 16, 20 },
		{ 3, 18, 19 }
	};

	for (int i = 0; i < n; i++)
		for (int j = 0; j < m; j++)
			map[i][j] = tempMap[i][j];
}

void print2DArr(int map[][SIZE_EXITS], int n, int m, ostream &os) {
	cout << "\n";
	for (int i = 0; i < n; i++)
		for (int j = 0; j < m; j++)
			cout << "\t" << map[i][j] << (j % m == m - 1 ? "\n" : ", ");
}

int startHunt(int const map[][SIZE_EXITS], int player, int wumpus, int bat1, int bat2, int pit1, int pit2, int &count) {
	count = 0;

	while (true) {
		if (player == wumpus) {
			cout << "\n\n\tYou awakened the Wumpus. He eats you. \n\tYou lose.";
			return -1;
		}
		else if (player == pit1 || player == pit2) {
			cout << "\n\n\tYou fell into a bottomless pit. \n\tYou lose... eventually...";
			return 0;
		}

		if (isHazardNear(map, player, wumpus))
			cout << "\n\n\tYou smell the unmistakable stench of a Wumpus";

		if (isHazardNear(map, player, bat1) || isHazardNear(map, player, bat2))
			cout << "\n\n\tYou hear the flapping of large wings";

		if (isHazardNear(map, player, pit1) || isHazardNear(map, player, pit2))
			cout << "\n\n\tYou feel an ominous breeze";

		cout << endl << endl;
		printRoomAndExits(map, player);
		cout << endl << endl;

		system("pause");
	}
}

bool isHazardNear(int const map[][SIZE_EXITS], int p, int h) {
	for (int i = 0; i < SIZE_EXITS; i++) {
		if (h == map[p][i])
			return true;
	}

	return false;
}

void printRoomAndExits(int const map[][SIZE_EXITS], int p) {
	cout
		<< "\tYou are in room " << p << endl
		<< "\tYou may go to rooms:" << endl;

	for (int i = 0; i < SIZE_EXITS; i++) {
		cout << "\t" << map[p][i];
	}
}<commit_msg>made arg const in print2DArr()<commit_after>#include "myHeader.h"
#include <iostream>
#include <fstream>
#include <string>
#include <iomanip>
using namespace std;

void printStringArr(const string a[], int n, ostream &os) {
	for (int i = 0; i < n; i++)
		os << "\n" << a[i];
}

int getIntInRange(int start, int end) {
	int x = getInt();

	while (x < start || x > end) {
		cout
			<< "\a\tYour number must be "
			<< (x < start ? "greater" : "less")
			<< " than or equal to "
			<< (x < start ? start : end)
			<< ". \n\tTry again: ";
		x = getInt();
	}

	return x;
}

int getInt() {
	double x = getNum();

	while (int(x) != x) {
		cout << "\a\tYour number is not an integer! \n\tTry Again: ";
		x = getNum();
	}

	return int(x);
}

double getNum() {
	double x;

	while (!(cin >> x)) {
		cin.clear();	cin.ignore(30, '\n');
		cout << "\a\tPlease no inapropriate characters! \n\tTry again: ";
	}
	cin.ignore(80, '\n');

	return x;
}

void loadStringArrayFromFile(string a[], int n, ifstream &ifs, bool &isLoaded) {
	for (int i = 0; i < n; i++)
		getline(ifs, a[i]);

	isLoaded = true;
}

void loadStats(int &gamesPlayed, int whoWon[], double whoWonPercent[], double numMoves[], int n, ifstream &ifs, bool &isLoaded) {

	while (ifs.peek() < '0' || ifs.peek() > '9')
		ifs.ignore();
	ifs >> gamesPlayed;

	while (ifs.peek() < '0' || ifs.peek() > '9')
		ifs.ignore();
	for (int i = 0; i < n; i++)
		ifs >> whoWon[i];

	while (ifs.peek() < '0' || ifs.peek() > '9')
		ifs.ignore();
	for (int i = 0; i < n; i++) {
		ifs >> whoWonPercent[i];
		ifs.ignore();	// for discarding '%'
	}

	while (ifs.peek() < '0' || ifs.peek() > '9')
		ifs.ignore();
	for (int i = 0; i < n; i++)
		ifs >> numMoves[i];

	isLoaded = true;
}

void printStats(int gamesPld, const int whoWon[], const double winPct[], const double numMvs[], int n, ostream &os) {

	os
		<< fixed << setprecision(1)
		<< "\nHunt the Wumpus Game Statistics"
		<< "\n\n\tGames Played: " << gamesPld
		<< "\n\n\tWho Won:"
		<< "\n\tPlayer\tWumpus\tPit\n";

	for (int i = 0; i < n; i++)
		os << "\t" << whoWon[i];

	os
		<< "\n\n\tWin Rate:"
		<< "\n\tPlayer\tWumpus\tPit\n";

	for (int i = 0; i < n; i++)
		os << "\t" << winPct[i] << "%";

	os
		<< "\n\n\tMoves per Game:"
		<< "\n\tLeast\tMost\tAverage\n"
		<< "\t" << int(numMvs[0])
		<< "\t" << int(numMvs[1])
		<< "\t" << numMvs[2];
}

void load2DArr(int map[][SIZE_EXITS], int const n, int const m) {
	int tempMap[21][3] = {
		{ 0, 0, 0 },		// room not actually used
		{ 2, 4, 19 },
		{ 1, 3, 6 },
		{ 2, 8, 20 },
		{ 1, 5, 9 },
		{ 4, 6, 11 },
		{ 2, 5, 7 },
		{ 6, 8, 12 },
		{ 3, 7, 13 },
		{ 4, 10, 16 },
		{ 9, 11, 14 },
		{ 5, 10, 12 },
		{ 7, 11, 15 },
		{ 8, 15, 18 },
		{ 10, 15, 17 },
		{ 12, 13, 14 },
		{ 9, 17, 19 },
		{ 14, 16, 18 },
		{ 13, 17, 20 },
		{ 1, 16, 20 },
		{ 3, 18, 19 }
	};

	for (int i = 0; i < n; i++)
		for (int j = 0; j < m; j++)
			map[i][j] = tempMap[i][j];
}

void print2DArr(int const map[][SIZE_EXITS], int n, int m, ostream &os) {
	cout << "\n";
	for (int i = 0; i < n; i++)
		for (int j = 0; j < m; j++)
			cout << "\t" << map[i][j] << (j % m == m - 1 ? "\n" : ", ");
}

int startHunt(int const map[][SIZE_EXITS], int player, int wumpus, int bat1, int bat2, int pit1, int pit2, int &count) {
	count = 0;

	while (true) {
		if (player == wumpus) {
			cout << "\n\n\tYou awakened the Wumpus. He eats you. \n\tYou lose.";
			return -1;
		}
		else if (player == pit1 || player == pit2) {
			cout << "\n\n\tYou fell into a bottomless pit. \n\tYou lose... eventually...";
			return 0;
		}

		if (isHazardNear(map, player, wumpus))
			cout << "\n\n\tYou smell the unmistakable stench of a Wumpus";

		if (isHazardNear(map, player, bat1) || isHazardNear(map, player, bat2))
			cout << "\n\n\tYou hear the flapping of large wings";

		if (isHazardNear(map, player, pit1) || isHazardNear(map, player, pit2))
			cout << "\n\n\tYou feel an ominous breeze";

		cout << endl << endl;
		printRoomAndExits(map, player);
		cout << endl << endl;

		system("pause");
	}
}

bool isHazardNear(int const map[][SIZE_EXITS], int p, int h) {
	for (int i = 0; i < SIZE_EXITS; i++) {
		if (h == map[p][i])
			return true;
	}

	return false;
}

void printRoomAndExits(int const map[][SIZE_EXITS], int p) {
	cout
		<< "\tYou are in room " << p << endl
		<< "\tYou may go to rooms:" << endl;

	for (int i = 0; i < SIZE_EXITS; i++) {
		cout << "\t" << map[p][i];
	}
}<|endoftext|>


<commit_before>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: http://www.qt-project.org/
**
**
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**************************************************************************/

#include "savefile.h"
#include "qtcassert.h"
#include "fileutils.h"

namespace Utils {

SaveFile::SaveFile(const QString &filename) :
    m_finalFileName(filename), m_finalized(true), m_backup(false)
{
}

SaveFile::~SaveFile()
{
    QTC_ASSERT(m_finalized, rollback());
}

bool SaveFile::open(OpenMode flags)
{
    QTC_ASSERT(!m_finalFileName.isEmpty() && fileName().isEmpty(), return false);

    QFile ofi(m_finalFileName);
    // Check whether the existing file is writable
    if (ofi.exists() && !ofi.open(QIODevice::ReadWrite)) {
        setErrorString(ofi.errorString());
        return false;
    }

    setAutoRemove(false);
    setFileTemplate(m_finalFileName);
    if (!QTemporaryFile::open(flags))
        return false;

    m_finalized = false; // needs clean up in the end
    if (ofi.exists())
        setPermissions(ofi.permissions()); // Ignore errors

    return true;
}

void SaveFile::rollback()
{
    remove();
    m_finalized = true;
}

bool SaveFile::commit()
{
    QTC_ASSERT(!m_finalized, return false);
    m_finalized = true;

    close();
    if (error() != NoError) {
        remove();
        return false;
    }

    QString finalFileName = Utils::FileUtils::resolveSymlinks(m_finalFileName);
    QString bakname = finalFileName + QLatin1Char('~');
    QFile::remove(bakname); // Kill old backup
    QFile::rename(finalFileName, bakname); // Backup current file
    if (!rename(finalFileName)) { // Replace current file
        QFile::rename(bakname, finalFileName); // Rollback to current file
        return false;
    }
    if (!m_backup)
        QFile::remove(bakname);

    return true;
}

} // namespace Utils
<commit_msg>properly sync file's data on commit<commit_after>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: http://www.qt-project.org/
**
**
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**************************************************************************/

#include "savefile.h"
#include "qtcassert.h"
#include "fileutils.h"
#ifdef Q_OS_WIN
#  include <windows.h>
#else
#  include <unistd.h>
#endif

namespace Utils {

SaveFile::SaveFile(const QString &filename) :
    m_finalFileName(filename), m_finalized(true), m_backup(false)
{
}

SaveFile::~SaveFile()
{
    QTC_ASSERT(m_finalized, rollback());
}

bool SaveFile::open(OpenMode flags)
{
    QTC_ASSERT(!m_finalFileName.isEmpty() && fileName().isEmpty(), return false);

    QFile ofi(m_finalFileName);
    // Check whether the existing file is writable
    if (ofi.exists() && !ofi.open(QIODevice::ReadWrite)) {
        setErrorString(ofi.errorString());
        return false;
    }

    setAutoRemove(false);
    setFileTemplate(m_finalFileName);
    if (!QTemporaryFile::open(flags))
        return false;

    m_finalized = false; // needs clean up in the end
    if (ofi.exists())
        setPermissions(ofi.permissions()); // Ignore errors

    return true;
}

void SaveFile::rollback()
{
    remove();
    m_finalized = true;
}

bool SaveFile::commit()
{
    QTC_ASSERT(!m_finalized, return false);
    m_finalized = true;

    if (!flush()) {
        remove();
        return false;
    }
#ifdef Q_OS_WIN
    FlushFileBuffers(handle());
#else
    fdatasync(handle());
#endif
    close();
    if (error() != NoError) {
        remove();
        return false;
    }

    QString finalFileName = Utils::FileUtils::resolveSymlinks(m_finalFileName);
    QString bakname = finalFileName + QLatin1Char('~');
    QFile::remove(bakname); // Kill old backup
    QFile::rename(finalFileName, bakname); // Backup current file
    if (!rename(finalFileName)) { // Replace current file
        QFile::rename(bakname, finalFileName); // Rollback to current file
        return false;
    }
    if (!m_backup)
        QFile::remove(bakname);

    return true;
}

} // namespace Utils
<|endoftext|>


<commit_before>// Copyright (C) 2015, 2016 Pierre-Luc Perrier <pluc-dev@the-pluc.net>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef abz_random_random_hpp
#define abz_random_random_hpp

/// @file abz/random/random.hpp
/// Pseudorandom numbers generation.

#include "abz/detail/macros.hpp"

#include <cmath> // std::nextafter
#include <limits>
#include <random>
#include <type_traits>

ABZ_NAMESPACE_BEGIN

/// @cond ABZ_INTERNAL
namespace _ {

/// Returns a per-thread PRNG engine.
/// @return A reference to a thread local instance of Engine.
template <class Engine>
Engine &thread_local_engine()
{
  // NOTE(pluc) random_device can actually throw: "Throws an implementation-defined exception
  // derived from std::exception if a random number could not be generated."
  thread_local Engine g{std::random_device{}()};
  return g;
}

template <class T, class Engine, class Enabled = void>
struct uniform_distribution;

template <class Integral, class Engine>
struct uniform_distribution<Integral, Engine, typename std::enable_if<std::is_integral<Integral>::value>::type> {
  using distribution_type = std::uniform_int_distribution<Integral>;
  using param_type = typename distribution_type::param_type;
  using result_type = Integral;

  static inline constexpr result_type default_min() { return result_type{0}; }
  static inline constexpr result_type default_max()
  {
    return std::numeric_limits<result_type>::max();
  }
  static inline result_type get(Engine &g, const Integral a, const Integral b)
  {
    return distribution_type{}(g, param_type{a, b});
  }
};

template <class Real, class Engine>
struct uniform_distribution<Real, Engine, typename std::enable_if<std::is_floating_point<Real>::value>::type> {
  using distribution_type = std::uniform_real_distribution<Real>;
  using param_type = typename distribution_type::param_type;
  using result_type = Real;

  static inline constexpr result_type default_min() { return Real{0}; }
  static inline constexpr result_type default_max() { return Real{1}; }
  static inline result_type get(Engine &g, const Real a, const Real b)
  {
    return distribution_type{}(
      g, param_type{a, std::nextafter(b, std::numeric_limits<result_type>::max())});
  }
};

} // namespace _
/// @endcond ABZ_INTERNAL

namespace random {

/// @brief Seeds the internal thread local engine with a new value.
///
/// The seed value is generated using std::random_device.
///
/// The library keep a local thread instance of each engine. Multiple calls from the same thread and
/// using the same Engine type will use the same generator. This function seeds the Engine's
/// instance of the calling thread.
///
/// @tparam Engine The type of engine for which the instance will be seeded.
///
/// @see seed(const Engine::result_type) rand
template <class Engine = std::default_random_engine>
inline void seed()
{
  _::thread_local_engine<Engine>().seed(std::random_device{}());
}

/// @overload
///
/// @param value The new seed value
///
/// @see seed rand
template <class Engine = std::default_random_engine>
inline void seed(const typename Engine::result_type value)
{
  _::thread_local_engine<Engine>().seed(value);
}

} // namespace random

/// Gets a (pseudo) random number uniformly distributed on the interval \f$[a, b]\f$.
///
/// Default paramaters are
/// @li \f$\{0, MAX(T)\}\f$ for integral types
/// @li \f$\{0.0, 1.0\}\f$ for floating point types
///
/// Requires that
/// @li \f$a \leq b\f$ for integral types
/// @li \f$(a \leq b) \land (b < MAX(T)) \land ((b - a) < MAX(T))\f$ for floating point
/// types
///
/// @note This functions uses a thread_local instance of the engine. To reinitialize this engine
/// with a new seed, see random::seed.
///
/// @warning For floating point types, some existing implementations have a bug where they may
/// occasionally return b (that is, std::nextafter(b, std::numeric_limits<Real>::max()) for this
/// function). GCC
/// #63176 #LLVM
/// #18767 LWG #2524.
///
/// @see random::seed()
///
/// @param a, b The interval of the generated numbers
///
/// @tparam T The type of number to generate (must be integral or floating point).
/// @tparam Engine The random number generator to use (must satisfy
/// UniformRandomNumberGenerator concept).
template <class T, class Engine = std::default_random_engine>
inline T rand(T a = _::uniform_distribution<T, Engine>::default_min(),
              T b = _::uniform_distribution<T, Engine>::default_max())
{
  return _::uniform_distribution<T, Engine>::get(_::thread_local_engine<Engine>(), a, b);
}

ABZ_NAMESPACE_END

#endif // abz_random_random_hpp
<commit_msg>[random] rand now accepts a reference to a generator<commit_after>// Copyright (C) 2015, 2016 Pierre-Luc Perrier <pluc-dev@the-pluc.net>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef abz_random_random_hpp
#define abz_random_random_hpp

/// @file abz/random/random.hpp
/// Pseudorandom numbers generation.

#include "abz/detail/macros.hpp"

#include <cmath> // std::nextafter
#include <limits>
#include <random>
#include <type_traits>

ABZ_NAMESPACE_BEGIN

/// @cond ABZ_INTERNAL
namespace _ {

/// Returns a per-thread PRNG engine.
/// @return A reference to a thread local instance of Engine.
template <class Engine>
Engine &thread_local_engine()
{
  // NOTE(pluc) random_device can actually throw: "Throws an implementation-defined exception
  // derived from std::exception if a random number could not be generated."
  thread_local Engine g{std::random_device{}()};
  return g;
}

template <class T, class Engine, class Enabled = void>
struct uniform_distribution;

template <class Integral, class Engine>
struct uniform_distribution<Integral, Engine, typename std::enable_if<std::is_integral<Integral>::value>::type> {
  using distribution_type = std::uniform_int_distribution<Integral>;
  using param_type = typename distribution_type::param_type;
  using result_type = Integral;

  static inline constexpr result_type default_min() { return result_type{0}; }
  static inline constexpr result_type default_max()
  {
    return std::numeric_limits<result_type>::max();
  }
  static inline result_type get(Engine &g, const Integral a, const Integral b)
  {
    return distribution_type{}(g, param_type{a, b});
  }
};

template <class Real, class Engine>
struct uniform_distribution<Real, Engine, typename std::enable_if<std::is_floating_point<Real>::value>::type> {
  using distribution_type = std::uniform_real_distribution<Real>;
  using param_type = typename distribution_type::param_type;
  using result_type = Real;

  static inline constexpr result_type default_min() { return Real{0}; }
  static inline constexpr result_type default_max() { return Real{1}; }
  static inline result_type get(Engine &g, const Real a, const Real b)
  {
    return distribution_type{}(
      g, param_type{a, std::nextafter(b, std::numeric_limits<result_type>::max())});
  }
};

} // namespace _
/// @endcond ABZ_INTERNAL

namespace random {

/// @brief Seeds the internal thread local engine with a new value.
///
/// The seed value is generated using std::random_device.
///
/// The library keep a local thread instance of each engine. Multiple calls from the same thread and
/// using the same Engine type will use the same generator. This function seeds the Engine's
/// instance of the calling thread.
///
/// @tparam Engine The type of engine for which the instance will be seeded.
///
/// @see seed(const Engine::result_type) rand
template <class Engine = std::default_random_engine>
inline void seed()
{
  _::thread_local_engine<Engine>().seed(std::random_device{}());
}

/// @overload
///
/// @param value The new seed value
///
/// @see seed rand
template <class Engine = std::default_random_engine>
inline void seed(const typename Engine::result_type value)
{
  _::thread_local_engine<Engine>().seed(value);
}

} // namespace random

/// Gets a (pseudo) random number uniformly distributed on the interval \f$[a, b]\f$.
///
/// Default paramaters are
/// @li \f$\{0, MAX(T)\}\f$ for integral types
/// @li \f$\{0.0, 1.0\}\f$ for floating point types
///
/// Requires that
/// @li \f$a \leq b\f$ for integral types
/// @li \f$(a \leq b) \land (b < MAX(T)) \land ((b - a) < MAX(T))\f$ for floating point
/// types
///
/// @warning For floating point types, some existing implementations have a bug where they may
/// occasionally return b (that is, std::nextafter(b, std::numeric_limits<Real>::max()) for this
/// function). GCC
/// #63176 #LLVM
/// #18767 LWG #2524.
///
/// @param e A reference to a randon bit generator.
/// @param a, b The interval of the generated numbers
///
/// @tparam T The type of number to generate (must be integral or floating point).
/// @tparam Engine The random number generator type (must satisfy UniformRandomBitGenerator
/// concept).
template <class T, class Engine>
inline auto rand(Engine &e,
                 T const a = _::uniform_distribution<T, Engine>::default_min(),
                 T const b = _::uniform_distribution<T, Engine>::default_max()) ->
  typename _::uniform_distribution<T, Engine>::result_type
{
  return _::uniform_distribution<T, Engine>::get(e, a, b);
}

/// @overload
///
/// This overload uses a thread local random bit generator. To reinitialize this engine with a new
/// seed, see random::seed.
///
/// @see random::seed()
template <class T, class Engine = std::default_random_engine>
inline auto rand(T const a = _::uniform_distribution<T, Engine>::default_min(),
                 T const b = _::uniform_distribution<T, Engine>::default_max()) ->
  typename _::uniform_distribution<T, Engine>::result_type
{
  return rand(_::thread_local_engine<Engine>(), a, b);
}

ABZ_NAMESPACE_END

#endif // abz_random_random_hpp
<|endoftext|>


<commit_before>#include "infer.hpp"
#include "ast.hpp"
#include "package.hpp"

#include <sstream>

namespace type {

  // try to open type `self` from signatures in `s`
  static mono open(const ref<state>& s, const mono& self);

  // foldr over row types
  template<class Init, class Func>
  static Init foldr_rows(const Init& init, mono self, const Func& func) {
    assert(self.kind() == kind::row());
    return self.match<Init>([&](const app& self) {
      const auto e = extension::unpack(self);
      return func(e.attr, e.head, foldr_rows(init, e.tail, func));
    }, [&](const mono& ) { return init; });
  }

  // foldr over function argument types. func is **not** called on result
  // type. note: you need to substitute in calls to func
  template<class Init, class Func>
  static Init foldr_args(const ref<state>& s,
                         const Init& init, mono self, const Func& func) {
    assert(self.kind() == kind::term());
    return s->substitute(self).match<Init>([&](const app& self) {
      const mono from = s->fresh();
      const mono to = s->fresh();

      try {
        s->unify(from >>= to, self);
      } catch(error& e) {
        // TODO don't use exceptions for control flow ffs
        return init;
      }

      return func(from, foldr_args(s, init, to, func));
    }, [&](const mono& self) {
      return init;
    } );
  }

  struct let {
    const ::list<ast::bind> defs;
    const ast::expr body;

    static symbol fix() { return "__fix__"; }

    // rewrite let as non-recursive let + fix **when defining functions**
    static let rewrite(const ast::let& self) {
      using ::list;
      const list<ast::bind> defs = map(self.defs, [](ast::bind self) {
          return self.value.match<ast::bind>
          ([&](const ast::abs& abs) {
            return ast::bind{self.name,
                             ast::app{ast::var{fix()},
                                      ast::abs{self.name >>= list<ast::abs::arg>(),
                                               self.value}
                                      >>= list<ast::expr>()}};
          },
            [&](const ast::expr& expr) { return self; });
        });

      return {defs, *self.body};
    }
  };

  // rewrite app as nested unary applications
  static ast::app rewrite(const ast::app& self) {
    const ast::expr& init = *self.func;
    return foldl(init, self.args, [](ast::expr func, ast::expr arg) {
        return ast::app(func, arg >>= list<ast::expr>());
      }).cast<ast::app>();
  }

  // reconstruct actual type from reified type: ... -> (type 'a) yields 'a
  static mono reconstruct(ref<state> s, mono self) {
    self = s->substitute(self);
    auto a = s->fresh();

    try {
      s->unify(ty(a), self);
      return a;
      // TODO don't use exceptions for control flow lol
    } catch(error& e) {
      auto from = s->fresh();
      auto to = s->fresh();

      s->unify(from >>= to, self);
      return reconstruct(s, to);
    }

  }

  // obtain constructor for a monotype
  static cst constructor(mono t) {
    if(auto self = t.get<app>()) {
      return constructor((*self)->ctor);
    }

    if(auto self = t.get<cst>()) {
      return *self;
    }

    // TODO restrictive?
    throw error("constructor must be a constant");
  }

  // try to open type `self` from signatures in `s`
  static mono open(const ref<state>& s, const mono& self) {
    // obtain type constructor from argument type
    const cst c = constructor(s->substitute(self));

    try {
      auto sig = s->sigs->at(c);

      const mono inner = s->fresh();
      s->unify(self >>= inner, s->instantiate(sig));

      return inner;
    } catch(std::out_of_range&) {
      std::stringstream ss;
      ss << "constructor " << tool::quote(c->name.get())
         << " has no associated signature";

      throw error(ss.str());
    }
  }

  ////////////////////////////////////////////////////////////////////////////////

  // error: unimplemented
  template<class T>
  static mono infer(const ref<state>& s, const T& self) {
    throw std::logic_error("infer unimplemented: " + tool::type_name(typeid(T)));
  }

  // var
  static mono infer(const ref<state>& s, const ast::var& self) {
    try {
      return s->instantiate(s->vars->find(self.name));
    } catch(std::out_of_range& e) {
      throw error("unbound variable " + tool::quote(self.name.get()));
    }
  }

  // initialize function scope with argument types
  static ref<state> function_scope(const ref<state>& s,
                                   const list<ast::abs::arg>& args) {
    auto sub = scope(s);

    for(auto arg: args) {
      const mono type = arg.match<mono>([&](symbol self) {
          return s->fresh();
        },
        [&](ast::abs::typed self) {
          // obtain reified type from annoatation
          const mono reified = infer(s, self.type);

          // TODO do we need gen/inst here?

          // extract concrete type from reified type
          const mono concrete = reconstruct(s, reified);

          return concrete;
        });

      sub->def(arg.name(), type);
    }

    return sub;
  }

  // abs
  static mono infer(const ref<state>& s, const ast::abs& self) {

    // function scope
    const auto sub = function_scope(s, self.args);

    const mono result = s->fresh();
    const mono sig = foldr(result, self.args, [&](auto arg, mono rhs) {
        const mono type = s->instantiate(sub->vars->find(arg.name()));
        return type >>= rhs;
      });

    // infer lambda body with augmented environment
    s->unify(result, infer(sub, *self.body));

    return sig;
  }

  // app
  static mono infer(const ref<state>& s, const ast::app& self) {
    // normalize application as unary
    const ast::app rw = rewrite(self);
    assert(size(rw.args) == 1);

    // infer func/arg types for application
    const auto with_inferred = [&](auto cont) {
      const mono func = infer(s, *rw.func);
      const mono arg = infer(s, rw.args->head);

      return cont(func, arg);
    };

    // check if application works with given func/arg type
    const auto check = [&](mono func, mono arg) {
      const mono ret = s->fresh();
      s->unify(func , arg >>= ret);
      return ret;
    };

    // TODO find a less stupid way of trying all cases?
    try {
      // normal case
      return with_inferred([&](mono func, mono arg) {
          return check(func, arg);
        });

    } catch(error& e) {

      try {
        // open func type and retry
        return with_inferred([&](mono func, mono arg) {
            return check(open(s, func), arg);
          });
      }
      catch(error& ) {  }

      try {
        // open arg type and retry
        return with_inferred([&](mono func, mono arg) {
            return check(func, open(s, arg));
          });
      }
      catch(error& ) {  }

      try {
        // open both func and arg types and retry
        return with_inferred([&](mono func, mono arg) {
            return check(open(s, func), open(s, arg));
          });
      }
      catch(error& ) {  }

      throw e;
    }

  }

  // non-recursive let
  static mono infer(const ref<state>& s, const let& self) {
    auto sub = scope(s);

    for(ast::bind def : self.defs) {
      sub->vars->locals.emplace(def.name, s->generalize(infer(s, def.value)));
    }

    return infer(sub, self.body);
  }

  // recursive let
  static mono infer(const ref<state>& s, const ast::let& self) {
    auto sub = scope(s);

    const mono a = sub->fresh();
    sub->def(let::fix(), (a >>= a) >>= a);

    return infer(sub, let::rewrite(self));
  }

  // sel
  static mono infer(const ref<state>& s, const ast::sel& self) {
    const mono tail = s->fresh(kind::row());
    const mono head = s->fresh(kind::term());

    const mono row = ext(self.name)(head)(tail);
    return record(row) >>= head;
  }

  // record attrs
  static mono infer(const ref<state>& s, const list<ast::record::attr>& attrs) {
    const mono init = empty;
    return foldr(init, attrs, [&](ast::record::attr attr, mono tail) {
        return ext(attr.name)(infer(s, attr.value))(tail);
      });
  }

  // record
  static mono infer(const ref<state>& s, const ast::record& self) {
    return record(infer(s, self.attrs));
  }

  // make
  static mono infer(const ref<state>& s, const ast::make& self) {
    // get signature type
    const poly sig = s->vars->find(self.type);

    auto sub = scope(s);

    const mono outer = s->fresh();
    const mono inner = sub->fresh();

    // instantiate signature at sub level prevents generalization of
    // contravariant side (variables only appearing in the covariant side will
    // be generalized)
    s->unify(ty(outer) >>= ty(inner), sub->instantiate(sig));

    // vanilla covariant type
    const poly reference = sub->generalize(inner);

    // build provided type
    const mono init = empty;
    const mono provided =
      record(foldr(init, self.attrs,
                   [&](const ast::record::attr attr, mono tail) {
                     return row(attr.name, infer(sub, attr.value)) |= tail;
                   }));

    // now also unify inner with provided type
    s->unify(inner, provided);

    // now generalize the provided type
    const poly gen = sub->generalize(inner);

    // generalization check: quantified variables in reference/gen should
    // substitute to the same variables
    std::set<var> quantified;
    for(const var& v : gen.forall) {
      assert(sub->substitute(v) == v);
      quantified.insert(v);
    }

    // make sure all reference quantified references substitute to quantified
    // variables
    for(const var& v : reference.forall) {
      const mono vs = sub->substitute(v);
      if(auto u = vs.get<var>()) {
        auto it = quantified.find(*u);
        if(it != quantified.end()) {
          continue;
        }
      }

      std::stringstream ss;
      logger(ss) << "failed to generalize " << gen
                 << " as " << reference;

      throw error(ss.str());
    }

    return outer;
  }

  // cond
  static mono infer(const ref<state>& s, const ast::cond& self) {
    const mono test = infer(s, *self.test);
    s->unify(test, boolean);

    const mono conseq = infer(s, *self.conseq);
    const mono alt = infer(s, *self.alt);

    const mono result = s->fresh();
    s->unify(result, conseq);
    s->unify(result, alt);

    return result;
  }

  // def
  static mono infer(const ref<state>& s, const ast::def& self) {
    const mono value =
      infer(s, ast::let(ast::bind{self.name, *self.value} >>= list<ast::bind>(),
                        ast::var{self.name}));
    try {
      s->def(self.name, value);
      return io(unit);
    } catch(std::runtime_error& e) {
      throw error(e.what());
    }
  }

  // use
  static mono infer(const ref<state>& s, const ast::use& self) {
    // infer value type
    const mono value = infer(s, *self.env);

    // make sure value type is a record
    const mono row = s->fresh(kind::row());
    s->unify(value, record(row));

    auto sub = scope(s);

    // fill sub scope with record contents
    using ::unit;
    foldr_rows(unit(), s->substitute(row), [&](symbol attr, mono t, unit) {
        // TODO generalization issue?
        sub->def(attr, t);
        return unit();
      });

    return infer(sub, *self.body);
  }

  // import
  static mono infer(const ref<state>& s, const ast::import& self) {
    auto it = s->vars->locals.find(self.package);
    if(it != s->vars->locals.end()) {
      // TODO delegate to def
      throw error("variable " + tool::quote(self.package.get()) + " already defined");
    }

    const package pkg = package::import(self.package);

    s->vars->locals.emplace(self.package, pkg.sig());
    return io(unit);
  }

  // infer kind from reified type
  static kind::any infer_kind(const ref<state>& s, mono self) {
    return foldr_args(s, kind::term(), self, [&](mono arg, kind::any k) {
      return infer_kind(s, open(s, s->substitute(arg))) >>= k;
    });
  }

  // module
  static mono infer(const ref<state>& s, const ast::module& self) {

    // module scope
    const auto sub = function_scope(s, self.args);

    // argument types
    const list<mono> args = map(self.args, [&](auto arg) {
      return s->instantiate(sub->vars->find(arg.name()));
    });

    // build module signature type
    const mono result = s->fresh();

    const mono sig = foldr(result, args, [&](mono arg, mono rhs) {
      return arg >>= rhs;
    });

    // infer attribute types in module scope
    const mono attrs = infer(sub, self.attrs);

    // recover inner type from reified types
    const mono inner =
      record(foldr_rows(empty, attrs, [&](symbol name, mono reified, mono rhs) {
        return row(name, reconstruct(sub, reified)) |= rhs;
      }));

    // compute kind from signature
    const kind::any k = infer_kind(s, sig);

    // create a new type constructor with given name/computed kind
    const cst c = make_ref<constant>(self.name, k);

    // in the meantime, return signature
    s->unify(result, record(attrs));
    return sig;
  }

  // lit
  static mono infer(const ref<state>&, const ast::lit<::boolean>& self) {
    return boolean;
  }

  static mono infer(const ref<state>&, const ast::lit<::integer>& self) {
    return integer;
  }

  static mono infer(const ref<state>&, const ast::lit<::real>& self) {
    return real;
  }

  ////////////////////////////////////////////////////////////////////////////////

  struct infer_visitor {
    using type = mono;

    template<class T>
    mono operator()(const T& self, const ref<state>& s) const {
      return infer(s, self);
    }

  };

  mono infer(const ref<state>& s, const ast::expr& self) {
    return self.visit(infer_visitor(), s);
  }

}
<commit_msg>getting there<commit_after>#include "infer.hpp"
#include "ast.hpp"
#include "package.hpp"

#include <sstream>

namespace type {

  // try to open type `self` from signatures in `s`
  static mono open(const ref<state>& s, const mono& self);

  // foldr over row types
  template<class Init, class Func>
  static Init foldr_rows(const Init& init, mono self, const Func& func) {
    assert(self.kind() == kind::row());
    return self.match<Init>([&](const app& self) {
      const auto e = extension::unpack(self);
      return func(e.attr, e.head, foldr_rows(init, e.tail, func));
    }, [&](const mono& ) { return init; });
  }

  // foldr over function argument types. func is **not** called on result
  // type. note: you need to substitute in calls to func
  template<class Init, class Func>
  static Init foldr_args(const ref<state>& s,
                         const Init& init, mono self, const Func& func) {
    assert(self.kind() == kind::term());
    return s->substitute(self).match<Init>([&](const app& self) {
      const mono from = s->fresh();
      const mono to = s->fresh();

      try {
        s->unify(from >>= to, self);
      } catch(error& e) {
        // TODO don't use exceptions for control flow ffs
        return init;
      }

      return func(from, foldr_args(s, init, to, func));
    }, [&](const mono& self) {
      return init;
    } );
  }

  template<class Init, class Func>
  static Init foldl_kind(const Init& init, const kind::any& self, const Func& func) {
    return self.match<Init>([&](const kind::constructor& self) {
      return foldl_kind(func(init, *self.from), *self.to, func);
    }, [&](const kind::constant& ) { return init; });
  }

  struct let {
    const ::list<ast::bind> defs;
    const ast::expr body;

    static symbol fix() { return "__fix__"; }

    // rewrite let as non-recursive let + fix **when defining functions**
    static let rewrite(const ast::let& self) {
      using ::list;
      const list<ast::bind> defs = map(self.defs, [](ast::bind self) {
          return self.value.match<ast::bind>
          ([&](const ast::abs& abs) {
            return ast::bind{self.name,
                             ast::app{ast::var{fix()},
                                      ast::abs{self.name >>= list<ast::abs::arg>(),
                                               self.value}
                                      >>= list<ast::expr>()}};
          },
            [&](const ast::expr& expr) { return self; });
        });

      return {defs, *self.body};
    }
  };

  // rewrite app as nested unary applications
  static ast::app rewrite(const ast::app& self) {
    const ast::expr& init = *self.func;
    return foldl(init, self.args, [](ast::expr func, ast::expr arg) {
        return ast::app(func, arg >>= list<ast::expr>());
      }).cast<ast::app>();
  }

  // reconstruct actual type from reified type: ... -> (type 'a) yields 'a
  static mono reconstruct(ref<state> s, mono self) {
    self = s->substitute(self);
    auto a = s->fresh();

    try {
      s->unify(ty(a), self);
      return a;
      // TODO don't use exceptions for control flow lol
    } catch(error& e) {
      auto from = s->fresh();
      auto to = s->fresh();

      s->unify(from >>= to, self);
      return reconstruct(s, to);
    }

  }

  // obtain constructor for a monotype
  static cst constructor(mono t) {
    if(auto self = t.get<app>()) {
      return constructor((*self)->ctor);
    }

    if(auto self = t.get<cst>()) {
      return *self;
    }

    // TODO restrictive?
    throw error("constructor must be a constant");
  }

  // try to open type `self` from signatures in `s`
  static mono open(const ref<state>& s, const mono& self) {
    // obtain type constructor from argument type
    const cst c = constructor(s->substitute(self));

    try {
      auto sig = s->sigs->at(c);

      const mono inner = s->fresh();
      s->unify(self >>= inner, s->instantiate(sig));

      return inner;
    } catch(std::out_of_range&) {
      std::stringstream ss;
      ss << "constructor " << tool::quote(c->name.get())
         << " has no associated signature";

      throw error(ss.str());
    }
  }

  ////////////////////////////////////////////////////////////////////////////////

  // error: unimplemented
  template<class T>
  static mono infer(const ref<state>& s, const T& self) {
    throw std::logic_error("infer unimplemented: " + tool::type_name(typeid(T)));
  }

  // var
  static mono infer(const ref<state>& s, const ast::var& self) {
    try {
      return s->instantiate(s->vars->find(self.name));
    } catch(std::out_of_range& e) {
      throw error("unbound variable " + tool::quote(self.name.get()));
    }
  }

  // initialize function scope with argument types
  static ref<state> function_scope(const ref<state>& s,
                                   const list<ast::abs::arg>& args) {
    auto sub = scope(s);

    for(auto arg: args) {
      const mono type = arg.match<mono>([&](symbol self) {
          return s->fresh();
        },
        [&](ast::abs::typed self) {
          // obtain reified type from annoatation
          const mono reified = infer(s, self.type);

          // TODO do we need gen/inst here?

          // extract concrete type from reified type
          const mono concrete = reconstruct(s, reified);

          return concrete;
        });

      sub->def(arg.name(), type);
    }

    return sub;
  }

  // abs
  static mono infer(const ref<state>& s, const ast::abs& self) {

    // function scope
    const auto sub = function_scope(s, self.args);

    const mono result = s->fresh();
    const mono sig = foldr(result, self.args, [&](auto arg, mono rhs) {
        const mono type = s->instantiate(sub->vars->find(arg.name()));
        return type >>= rhs;
      });

    // infer lambda body with augmented environment
    s->unify(result, infer(sub, *self.body));

    return sig;
  }

  // app
  static mono infer(const ref<state>& s, const ast::app& self) {
    // normalize application as unary
    const ast::app rw = rewrite(self);
    assert(size(rw.args) == 1);

    // infer func/arg types for application
    const auto with_inferred = [&](auto cont) {
      const mono func = infer(s, *rw.func);
      const mono arg = infer(s, rw.args->head);

      return cont(func, arg);
    };

    // check if application works with given func/arg type
    const auto check = [&](mono func, mono arg) {
      const mono ret = s->fresh();
      s->unify(func , arg >>= ret);
      return ret;
    };

    // TODO find a less stupid way of trying all cases?
    try {
      // normal case
      return with_inferred([&](mono func, mono arg) {
          return check(func, arg);
        });

    } catch(error& e) {

      try {
        // open func type and retry
        return with_inferred([&](mono func, mono arg) {
            return check(open(s, func), arg);
          });
      }
      catch(error& ) {  }

      try {
        // open arg type and retry
        return with_inferred([&](mono func, mono arg) {
            return check(func, open(s, arg));
          });
      }
      catch(error& ) {  }

      try {
        // open both func and arg types and retry
        return with_inferred([&](mono func, mono arg) {
            return check(open(s, func), open(s, arg));
          });
      }
      catch(error& ) {  }

      throw e;
    }

  }

  // non-recursive let
  static mono infer(const ref<state>& s, const let& self) {
    auto sub = scope(s);

    for(ast::bind def : self.defs) {
      sub->vars->locals.emplace(def.name, s->generalize(infer(s, def.value)));
    }

    return infer(sub, self.body);
  }

  // recursive let
  static mono infer(const ref<state>& s, const ast::let& self) {
    auto sub = scope(s);

    const mono a = sub->fresh();
    sub->def(let::fix(), (a >>= a) >>= a);

    return infer(sub, let::rewrite(self));
  }

  // sel
  static mono infer(const ref<state>& s, const ast::sel& self) {
    const mono tail = s->fresh(kind::row());
    const mono head = s->fresh(kind::term());

    const mono row = ext(self.name)(head)(tail);
    return record(row) >>= head;
  }

  // record attrs
  static mono infer(const ref<state>& s, const list<ast::record::attr>& attrs) {
    const mono init = empty;
    return foldr(init, attrs, [&](ast::record::attr attr, mono tail) {
        return ext(attr.name)(infer(s, attr.value))(tail);
      });
  }

  // record
  static mono infer(const ref<state>& s, const ast::record& self) {
    return record(infer(s, self.attrs));
  }

  // make
  static mono infer(const ref<state>& s, const ast::make& self) {
    // get signature type
    const poly sig = s->vars->find(self.type);

    auto sub = scope(s);

    const mono outer = s->fresh();
    const mono inner = sub->fresh();

    // instantiate signature at sub level prevents generalization of
    // contravariant side (variables only appearing in the covariant side will
    // be generalized)
    s->unify(ty(outer) >>= ty(inner), sub->instantiate(sig));

    // vanilla covariant type
    const poly reference = sub->generalize(inner);

    // build provided type
    const mono init = empty;
    const mono provided =
      record(foldr(init, self.attrs,
                   [&](const ast::record::attr attr, mono tail) {
                     return row(attr.name, infer(sub, attr.value)) |= tail;
                   }));

    // now also unify inner with provided type
    s->unify(inner, provided);

    // now generalize the provided type
    const poly gen = sub->generalize(inner);

    // generalization check: quantified variables in reference/gen should
    // substitute to the same variables
    std::set<var> quantified;
    for(const var& v : gen.forall) {
      assert(sub->substitute(v) == v);
      quantified.insert(v);
    }

    // make sure all reference quantified references substitute to quantified
    // variables
    for(const var& v : reference.forall) {
      const mono vs = sub->substitute(v);
      if(auto u = vs.get<var>()) {
        auto it = quantified.find(*u);
        if(it != quantified.end()) {
          continue;
        }
      }

      std::stringstream ss;
      logger(ss) << "failed to generalize " << gen
                 << " as " << reference;

      throw error(ss.str());
    }

    return outer;
  }

  // cond
  static mono infer(const ref<state>& s, const ast::cond& self) {
    const mono test = infer(s, *self.test);
    s->unify(test, boolean);

    const mono conseq = infer(s, *self.conseq);
    const mono alt = infer(s, *self.alt);

    const mono result = s->fresh();
    s->unify(result, conseq);
    s->unify(result, alt);

    return result;
  }

  // def
  static mono infer(const ref<state>& s, const ast::def& self) {
    const mono value =
      infer(s, ast::let(ast::bind{self.name, *self.value} >>= list<ast::bind>(),
                        ast::var{self.name}));
    try {
      s->def(self.name, value);
      return io(unit);
    } catch(std::runtime_error& e) {
      throw error(e.what());
    }
  }

  // use
  static mono infer(const ref<state>& s, const ast::use& self) {
    // infer value type
    const mono value = infer(s, *self.env);

    // make sure value type is a record
    const mono row = s->fresh(kind::row());
    s->unify(value, record(row));

    auto sub = scope(s);

    // fill sub scope with record contents
    using ::unit;
    foldr_rows(unit(), s->substitute(row), [&](symbol attr, mono t, unit) {
        // TODO generalization issue?
        sub->def(attr, t);
        return unit();
      });

    return infer(sub, *self.body);
  }

  // import
  static mono infer(const ref<state>& s, const ast::import& self) {
    auto it = s->vars->locals.find(self.package);
    if(it != s->vars->locals.end()) {
      // TODO delegate to def
      throw error("variable " + tool::quote(self.package.get()) + " already defined");
    }

    const package pkg = package::import(self.package);

    s->vars->locals.emplace(self.package, pkg.sig());
    return io(unit);
  }

  // infer kind from reified type
  static kind::any infer_kind(const ref<state>& s, mono self) {
    return foldr_args(s, kind::term(), self, [&](mono arg, kind::any k) {
      return infer_kind(s, open(s, s->substitute(arg))) >>= k;
    });
  }

  // module
  static mono infer(const ref<state>& s, const ast::module& self) {

    // module scope
    const auto sub = function_scope(s, self.args);

    // argument types
    const list<mono> args = map(self.args, [&](auto arg) {
      return s->instantiate(sub->vars->find(arg.name()));
    });

    // build module signature type
    const mono result = s->fresh();

    const mono sig = foldr(result, args, [&](mono arg, mono rhs) {
      return arg >>= rhs;
    });

    // infer attribute types in module scope
    const mono attrs = infer(sub, self.attrs);

    // recover inner type from reified types
    const mono inner =
      record(foldr_rows(empty, attrs, [&](symbol name, mono reified, mono rhs) {
        return row(name, reconstruct(sub, reified)) |= rhs;
      }));

    // infer kind from signature
    const kind::any k = infer_kind(s, sig);

    // create a new type constructor with given name/computed kind
    const cst c = make_ref<constant>(self.name, k);

    // apply constructor to the right type variables
    const mono outer = foldl_kind(mono(c), k, [&](mono lhs, kind::any k) {
      return lhs(s->fresh(k));
    });

    // unify properly kinded variables to the right input variables

    // in the meantime, return signature
    s->unify(result, record(attrs));
    return sig;
  }

  // lit
  static mono infer(const ref<state>&, const ast::lit<::boolean>& self) {
    return boolean;
  }

  static mono infer(const ref<state>&, const ast::lit<::integer>& self) {
    return integer;
  }

  static mono infer(const ref<state>&, const ast::lit<::real>& self) {
    return real;
  }

  ////////////////////////////////////////////////////////////////////////////////

  struct infer_visitor {
    using type = mono;

    template<class T>
    mono operator()(const T& self, const ref<state>& s) const {
      return infer(s, self);
    }

  };

  mono infer(const ref<state>& s, const ast::expr& self) {
    return self.visit(infer_visitor(), s);
  }

}
<|endoftext|>


<commit_before>// vim:ts=2:sw=2:expandtab:autoindent:filetype=cpp:
/*
The MIT License

Copyright (c) 2008, 2009 Aristid Breitkreuz, Ash Berlin, Ruediger Sonderfeld

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/

#ifndef FLUSSPFERD_GETOPT_HPP
#define FLUSSPFERD_GETOPT_HPP

#include <boost/optional.hpp>
#include <boost/none.hpp>

namespace flusspferd {

class string;
class object;
class array;

void load_getopt_module(object container);

/**
 * Parse the options.
 *
 * Specification syntax:
 *
 * @code
{
  "name": {
    "alias": ["abc", "d"],
    "argument": "none", // or "optional" or "required"
    "argument_type": "file", // or "dir" or "module" or ...
    "argument_bash": "bash script", // completion script for unkown types
    "doc": "documentation string"
    "callback": myfunction // takes (option, argument)
  },
  "name2": {}
}
@endcode
 *
 * @return
 * @code
{
  "name": ["arguments"],
  ...,
  "_": ["arguments"]
}
@endcode
 *
 * There are short options (-x) and long options (--xy). Short options cannot
 * take optional arguments, they will always @b require arguments or not accept
 * any at all.
 */
object getopt(
  object spec, boost::optional<array const &> const &arguments = boost::none);

/**
 * Returns a help text to a corresponding getopt call
 *
 */
string getopt_help(object spec);

/**
 * Returns a (nroff formated) manpage part to a corresponding getopt call
 *
 */
string getopt_man(object spec);

/**
 * Returns the content of a bash_completion function
 *
 * @code
 cout << "_foo() {\n" + getopt_bash(spec) + "}\ncomplete -F _foo foo\n";
@endcode
 */
string getopt_bash(object spec);
}

#endif
<commit_msg>improved documentation for getopt_bash<commit_after>// vim:ts=2:sw=2:expandtab:autoindent:filetype=cpp:
/*
The MIT License

Copyright (c) 2008, 2009 Aristid Breitkreuz, Ash Berlin, Ruediger Sonderfeld

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/

#ifndef FLUSSPFERD_GETOPT_HPP
#define FLUSSPFERD_GETOPT_HPP

#include <boost/optional.hpp>
#include <boost/none.hpp>

namespace flusspferd {

class string;
class object;
class array;

void load_getopt_module(object container);

/**
 * Parse the options.
 *
 * Specification syntax:
 *
 * @code
{
  "name": {
    "alias": ["abc", "d"],
    "argument": "none", // or "optional" or "required"
    "argument_type": "file", // or "dir" or "module" or ...
    "argument_bash": "bash script", // completion script for unkown types
    "doc": "documentation string"
    "callback": myfunction // takes (option, argument)
  },
  "name2": {}
}
@endcode
 *
 * @return
 * @code
{
  "name": ["arguments"],
  ...,
  "_": ["arguments"]
}
@endcode
 *
 * There are short options (-x) and long options (--xy). Short options cannot
 * take optional arguments, they will always @b require arguments or not accept
 * any at all.
 */
object getopt(
  object spec, boost::optional<array const &> const &arguments = boost::none);

/**
 * Returns a help text to a corresponding getopt call
 *
 */
string getopt_help(object spec);

/**
 * Returns a (nroff formated) manpage part to a corresponding getopt call
 *
 */
string getopt_man(object spec);

/**
 * Returns the content of a bash_completion function
 *
 * Has completions for all argument types supported by compgen/complete -A.
 * See http://www.gnu.org/software/bash/manual/bashref.html#Programmable-Completion-Builtins
 * Use the "argument_bash" property for your own completion scripts.
 *
 * @code
 cout << "_foo() {\n" + getopt_bash(spec) + "}\ncomplete -F _foo foo\n";
@endcode
 */
string getopt_bash(object spec);
}

#endif
<|endoftext|>


<commit_before>/*

Copyright (c) 2007, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#ifndef TORRENT_ASSERT

#include "libtorrent/config.hpp"
#include <string>

#ifdef __GNUC__
std::string demangle(char const* name);
#endif

#if (defined __linux__ || defined __MACH__) && defined __GNUC__ && !defined(NDEBUG)

TORRENT_EXPORT void assert_fail(const char* expr, int line, char const* file, char const* function);
#define TORRENT_ASSERT(x) if (x) {} else assert_fail(#x, __LINE__, __FILE__, __PRETTY_FUNCTION__)

#else
#include <cassert>
#define TORRENT_ASSERT(x) assert(x)
#endif

#endif

<commit_msg>fixed warning on gcc 4.3<commit_after>/*

Copyright (c) 2007, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#ifndef TORRENT_ASSERT

#include "libtorrent/config.hpp"
#include <string>

#ifdef __GNUC__
std::string demangle(char const* name);
#endif

#if (defined __linux__ || defined __MACH__) && defined __GNUC__ && !defined(NDEBUG)

TORRENT_EXPORT void assert_fail(const char* expr, int line, char const* file, char const* function);
#define TORRENT_ASSERT(x) do { if (x) {} else assert_fail(#x, __LINE__, __FILE__, __PRETTY_FUNCTION__); } while (false)

#else
#include <cassert>
#define TORRENT_ASSERT(x) assert(x)
#endif

#endif

<|endoftext|>


<commit_before>#pragma once

#include <initializer_list>
#include <map>
#include <memory>
#include <utility>
#include <mos/gfx/mesh.hpp>

namespace mos {
namespace gfx {

/**
 * @brief Keyframe animation, interpolation between meshes.
 */
class Animation {
public:
  Animation();
  /**
   * @brief Animation default contructor
   */
  Animation(const std::map<unsigned int, std::shared_ptr<Mesh const>> keyframes,
            const unsigned int frame_rate = 30);
  /**
   * @brief Animation constructor.
   * @param keyframes Map of keys and shared Meshes
   */
  Animation(std::initializer_list<
      std::pair<unsigned int, std::shared_ptr<Mesh const>>>
            keyframes,
            const unsigned int frame_rate = 30);

  /**
   *@brief Destructor.
   */
  ~Animation();

  Animation(const std::string &path);

  /**
   * @brief update, move the animation forward.
   * @param dt How much time to progress.
   */
  void update(const float dt);

  /**
   * @brief Current frame
   * @return frame
   */
  unsigned int frame() const;

  /**
   * @brief reset, restart the animation.
   */
  void reset();

  /**
   * @brief Set frame rate.
   */
  void frame_rate(const unsigned int frame_rate);

  /**
   * @brief Frame rate in frames per second.
   * @return
   */
  unsigned int frame_rate() const;

  /**
   * @brief The mesh, which is animated.
   * @return shared_ptr to mesh.
   */
  std::shared_ptr<Mesh> mesh();

private:
  float time_;
  std::map<unsigned int, std::shared_ptr<const Mesh>> keyframes_;
  std::shared_ptr<Mesh> mesh_;
  unsigned int frame_rate_;
};
}
}
<commit_msg>Cleanup animation<commit_after>#pragma once

#include <mos/gfx/mesh.hpp>
#include <initializer_list>
#include <map>
#include <memory>
#include <utility>

namespace mos {
namespace gfx {

/** Keyframe animation, interpolation between meshes. */
class Animation {
public:
  Animation();
  Animation(const std::map<unsigned int, std::shared_ptr<Mesh const>> keyframes,
            const unsigned int frame_rate = 30);
   Animation(std::initializer_list<
      std::pair<unsigned int, std::shared_ptr<Mesh const>>>
            keyframes,
            const unsigned int frame_rate = 30);

  ~Animation();

  Animation(const std::string &path);

  void update(const float dt);

  /** Current frame */
  unsigned int frame() const;

  /** Restart the animation. */
  void reset();

  /** Set frame rate. */
  void frame_rate(const unsigned int frame_rate);

  /** Frames per second. */
  unsigned int frame_rate() const;

  /** The mesh being animated. */
  std::shared_ptr<Mesh> mesh();

private:
  float time_;
  std::map<unsigned int, std::shared_ptr<const Mesh>> keyframes_;
  std::shared_ptr<Mesh> mesh_;
  unsigned int frame_rate_;
};
}
}
<|endoftext|>