Misc.

The following code snippets have no direct relation to computing flow fields, etc. but may be of use in constructing a complete program.

Reading initialization files

This is an example of using associative arrays and string parsing in D to initialize non-trivial variables: a vector and a tuple.

import
  std.stdio, std.conv, std.regex,
  std.typetuple, std.string;


void main()
{
  /// open input file
  File f;
  f.open("input.txt", "r");


  /// parse input file
  string input[string];
  string key, val;

  auto lvalFmt = regex(r"^\s*(\w+)\s*=");
  auto rvalFmt = regex(r"=\s*(.+)\s*;");

  foreach(ref string line; lines(f))
  {
    auto lval = match(line, lvalFmt);
    if(lval.captures.length > 1)
    {
      auto rval = match(line, rvalFmt);
      if(rval.captures.length > 1)
      {
        /// store entry
        key = lval.captures[1];
        val = rval.captures[1];
        input[key] = val;
      }
    }
  }


  /// initialize variables
  auto U = new double[3];
  TypeTuple!(int, double) quit;

  U = parse!(typeof(U))(input["U"]);

  auto buf = input["quit"];
  foreach(i, T; quit)
  {
    munch(buf, "[, ]");
    quit[i] = parse!(typeof(T))(buf);
  }

  writeln(U);
  writeln([quit]);
}

The input file is written as

U = [1.12, 2, -4.2e-4]; // ref. velocity
quit = [1000, 0.001]; // iter. cut-off (max iter, min norm)

Calling a D function from C

This is an example to show how to call D code from C. The first listing shows the C top-level which initializes the D runtime environment and then calls the D function.

#include <stdio.h>
#include <stdlib.h>

struct Data {
  int* idx;
  int idxLen;
};

char rt_init(long long);
char rt_term(long long);
void procData(struct Data*);

void main() {
  int i;
  struct Data *data;
  data = malloc(sizeof(struct Data));

  data->idxLen = 5;

  /// call D functions
  rt_init(0); /// initialize core.runtime
  procData(data);
  rt_term(0); /// terminate core.runtime

  printf("for [0..%d)\n", data->idxLen);
  for (i = 0; i < data->idxLen; ++i) {
    printf("-%d^%d = %d\n", i, i, data->idx[i]);
  }
}

The second listing shows the D function in which a structure element is allocated and initialized. To link the program, a third file is required which declares an empty D main function. Compilation can be performed with gcc and dmd respectively, then link with gcc using DFLAGS from the dmd.conf file.

import std.stdio, std.c.stdlib;

struct DataCp {
  int[] idx;
}

extern (C)
struct Data {
  int* idx;
  int idxLen;
}

extern (C)
void procData(ref Data data)
{
  writeln("entered D function");

  /// allocate array
  data.idx = cast(typeof(data.idx))
    malloc(data.idxLen * (*data.idx).sizeof);

  /// initialize elements
  for (int i=0; i<data.idxLen; ++i) {
    data.idx[i] = i^^i;
  }

  /// reference array with D array
  DataCp dataCp;
  dataCp.idx = data.idx[0..data.idxLen];

  /// modify elements via D array
  foreach (ref e; dataCp.idx) {
    e = -e;
  }

  writeln("exiting D function");
}

Links

DMD

Reference D compiler

Compilation with Python

Examples of a scanner, lexer and parser.

Dynamically typed languages

Paper about the benefits of dynamically typed languages.

Writing a compiler

Introduction to compilers, via Converge.

Bash tutorial

Sed tutorial

Regular expressions

Codes

Reading input file

C calls D

D calls C

Articles

Compiler construction

What is D?