A Taste of Mango

A group of word count programs written in C++ and the the C variant D.

C++ example #1

#include <algorithm>
#include <cstdio>
#include <fstream>
#include <iterator>
#include <map>
#include <vector>

bool isWordStartChar (char c)	{ return isalpha(c); }
bool isWordEndChar (char c)	{ return !isalnum(c); }

int main (int argc, char const* argv[])
{
    using namespace std;
    printf("Lines Words Bytes File:\n");

    map<string, int> dict;
    int tLines = 0, tWords = 0, tBytes = 0;
    for(int i = 1; i < argc; i++)
    {
	ifstream file(argv[i]);
	istreambuf_iterator<char> from(file.rdbuf()), to;
	vector<char> v(from, to);
	vector<char>::iterator first = v.begin(), last = v.end(), bow, eow;

	int numLines = count(first, last, '\n');
	int numWords = 0;
	int numBytes = last - first;

	for(eow = first; eow != last; )
	{
	    bow = find_if(eow, last, isWordStartChar);
	    eow = find_if(bow, last, isWordEndChar);
	    if(bow != eow)
		++dict[string(bow, eow)], ++numWords;
	}

	printf("%5d %5d %5d %s\n", numLines, numWords, numBytes, argv[i]);

	tLines += numLines;
	tWords += numWords;
	tBytes += numBytes;
    }

    if(argc > 2)
	    printf("-----------------------\n%5d %5d %5d\n", tLines, tWords, tBytes);
    printf("-----------------------\n\n");

    for(map<string, int>::const_iterator it = dict.begin(); it != dict.end(); ++it)
	    printf("%5d %s\n", it->second, it->first.c_str());

    return 0;
}
C++ example #2
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <cstdio>
#include <map>

int main( int argc, char* argv[] )
{
  int w_total = 0;
  int l_total = 0;
  int c_total = 0;
  std::map< std::string, int > dictionary;

  printf("   lines   words   bytes file\n" );
  for ( int i = 1; i < argc; ++i )
  {
    std::ifstream input_file( argv[i] );
    std::ostringstream buffer;
    buffer << input_file.rdbuf();
    std::string input( buffer.str() );

    int w_cnt = 0;
    int l_cnt = 0;
    int c_cnt = 0;
    bool inword = false;
    int wstart = 0;
    for ( unsigned int j = 0; j < input.length(); j++ )
    {
      char c = input[j];
      if (c == '\n')
        ++l_cnt;
      if (c >= '0' && c <= '9')
      {
      }
      else if (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z')
      {
        if (!inword)
        {
          wstart = j;
          inword = true;
          ++w_cnt;
        }
      }
      else if (inword)
      {
        std::string word = input.substr( wstart, j - wstart );
        std::map< std::string, int >::iterator it = dictionary.find( word );
        if ( it == dictionary.end() )
          dictionary[word] = 1;
        else
          ++it->second;
        inword = false;
      }
      ++c_cnt;
    }

    if (inword)
    {
      std::string w = input.substr( wstart );
      std::map< std::string, int >::iterator it = dictionary.find( w );
      if ( it == dictionary.end() )
        dictionary[w] = 1;
      else
        ++it->second;
    }

    printf("%d\t%d\t%d\t %s\n", l_cnt, w_cnt, c_cnt, argv[i]);
    l_total += l_cnt;
    w_total += w_cnt;
    c_total += c_cnt;
  }

  if (argc > 2)
  {
    printf("--------------------------------------\n%d\t%\d\t%d\t total",
l_total, w_total, c_total);
  }

  printf("--------------------------------------\n");
  for( std::map< std::string, int >::const_iterator cit =
dictionary.begin(), cend_it = dictionary.end(); cit != cend_it; ++cit )
    printf( "%d %s\n", cit->second, cit->first.c_str() );
}
D example
import stdio;
import file;

int main (char[][] args)
{
    int w_total;
    int l_total;
    int c_total;
    int[char[]] dictionary;

    printf("   lines   words   bytes file\n");
    for (int i = 1; i < args.length; ++i)
    {
        char[] input;
        int w_cnt, l_cnt, c_cnt;
        int inword;
        int wstart;

        input = File.read(args[i]);

        for (int j = 0; j < input.length; j++)
        {   char c;

            c = input[j];
            if (c == "\n")
                ++l_cnt;
            if (c >= "0" && c <= "9")
            {
            }
            else if (c >= "a" && c <= "z" ||
                c >= "A" && c <= "Z")
            {
                if (!inword)
                {
                    wstart = j;
                    inword = 1;
                    ++w_cnt;
                }
            }
            else if (inword)
            {   char[] word = input[wstart .. j];

                dictionary[word]++;
                inword = 0;
            }
            ++c_cnt;
        }
        if (inword)
        {   char[] word = input[wstart .. input.length];
            dictionary[word]++;
        }
        printf("%8lu%8lu%8lu %s\n", l_cnt, w_cnt, c_cnt, (char *)args[i]);
        l_total += l_cnt;
        w_total += w_cnt;
        c_total += c_cnt;
    }

    if (args.length > 2)
    {
        printf("--------------------------------------\n%8lu%8lu%8lu total",
            l_total, w_total, c_total);
    }

    printf("--------------------------------------\n");
    char[][] keys = dictionary.keys;
    for (int i = 0; i < keys.length; i++)
    {   char[] word;

        word = keys[i];
        printf("%3d %.*s\n", dictionary[word], word);
    }
    return 0;
}


A word count program written in Mango.


module wc;

import std/io, std/types, std/util, sys/args;

**
** define a 32 bit cardinal (unsigned integer) for tracking results
**

type count of cardinal/32 having overflow checked, conversion automatic;

**
** Define the width of an output field, length of a line, and the seperator
**

literal 
  field_size is 10;
  line_width is 80;
  file_field_size is line_width - field_size * 3;
  file_indent is 2;
  seperator is ('-', line_width);
  graph_width is 79;

**
** Create field formating constants to save some typing
**

constant 
  center_format of io_format is [width=field_size, align=center];
  right_format of io_format is [width=field_size, align=right];
  file_header_format of io_format is [width=file_field_size, offset=file_indent, align=center];
  file_text_format of io_format is [width=file_field_size, offset=file_indent, align=left];

**
** Character masks for classification
** 

function alpha_numeric with ascii yielding boolean is
  operand in 'a' to 'z' or operand in 'A' to 'Z' or operand in '0' to '9';

constant 
  alpha_numeric_mask of ascii mask is every x in <range, ascii> where x is alpha_numeric yielding x;
  whitespace_mask of ascii mask is [' ', '\n', '\t'];
  line_mask of ascii mask is not '\n';

**
** Iterator to generate a stream of words from the source text. 
** Iterator quits when result is <stop>. (i.e. nothing is returned)
** Note: operand is really (ascii list)&, result is [ascii+ string element]
**

iterator tokenizer with ascii list yielding [ascii+] string is
  state
    mark, index of integer/32;

  prelude
    set index;

  query  
    while index <= operand size and operand[index] in whitespace_mask do
      incr index;

    assign index into mark;

    while index <= operand size and operand[index] in alpha_numeric_mask do
      incr index;        

    evaluate operand, mark to index with create_string into result when index - mark > 0;

  finale
    nothing;

**
** The wc program
**

program wc with args of args_string is

   declare w_total, l_total, c_total of count;

   **
   ** graph is a cumulative array that maps ascii strings to count
   ** it is used to count the frequency of words in the files
   **

   declare graph of <[ascii+] string, count> graph{graph_width};

   **
   ** Write the table header to stdout
   **

   print center_format -> "lines", center_format -> "words", center_format -> "bytes";
   print file_header_format -> "file", eol;
   print seperator, eol;

   **
   ** process each file on the command line
   **

  mainloop:
   foreach name in args do
    begin
      declare l_cnt, w_cnt, c_cnt of count;
      
      **
      ** examine each line in the text file 
      ** count the words using the tokenizer and record frequency in the graph
      **

      open file of ascii text where path=name, mode=read;

      foreach line in file over (l_cnt) do
        foreach word in line using tokenizer over (w_cnt) do
           add 1 at word into graph;
        incr c_cnt with line size;
      
      close file;

      **
      ** output results for this file and add results to total
      **

      print right_format -> l_cnt, right_format -> w_cnt, right_format -> c_cnt;
      print file_text_format -> name, eol;
      
      incr l_total with l_cnt;
      incr w_total with w_cnt;
      incr c_total with c_cnt;
    end

   **
   ** Output the totals
   **

   if args size > 1 then
     print seperator, eol;
     print right_format -> l_total, right_format -> w_total, right_format -> c_total;
     print (' ', file_indent), "total" , eol;
   
   **
   ** Output word frequency
   ** 
   
   print eol, seperator, eol;
   
   foreach <name, value> in graph do
     print [width=5] -> value, (' ', 2), name, eol;


A snippet of code written in C++.


Type * Create_Dimension_Type(Universe * u, TypeClass type, Type * target, StringList * list) {
    hash_code h = 0;

    {
        StringListIter iter(list);
        
        for (String name = iter.first(); iter.more(); name = iter.next()) {
            h += compute_hash_code(name);
        }
    }

    {
        TypeTableIter iter(u->type_table, h);

        for (Type * t = iter.first(); iter.more(); t = iter.next()) {
            if (t->type == type && t->terms == list->size) {
                StringListIter iter(list);
                
                String name;
                Field * f;
                for (name = iter.first(), f = t->fields; iter.more() && f != NULL; 
                     name = iter.next(), f = f->next) {
                    if (name != f->name)
                        break;
                }
                
                if (f == NULL && !iter.more()) {
                    return t;
                }
            }
        }
    }


    Type * t = Create_Type(u, type);
    
    {
        Field * last = NULL;
        
        StringListIter iter(list);
        
        for (String name = iter.first(); iter.more(); name = iter.next()) {
            Field * f = Create_Field(u, FT_FIELD);
            f->name = name;
            f->t = target;
            
            if (last == NULL) {
                t->fields = f;
            }
            else {
                last->next = f;
            }
            
            last = f;
        }
        break;
    default:
        quit;
    }

    u->type_table->add(t, h);

    return t;
}


An equivalent codec rendered in Mango.


procedure create_dimension_type with u of Universe', type of Type_Class, target of Type', 
            list of ascii+ string list yielding Type is

   compute h with name in list yielding compute_hash(name);

   find (result) 
      with t in u.type_table at h where (t.type == type and t.terms == list size)
         and_then all name in list, f in t.fields where name == f.name
      else_insert get Type where type = type, 
         fields = every name in list yielding get Field entry where type=field, name=name, t=target
      yielding t;

Eratosthenes Sieve prime number calculation in D

bit flags[8191];
 
int main()
{   int     i, prime, k, count, iter;

    printf("10 iterations\n");
    for (iter = 1; iter <= 10; iter++)
    {   count = 0;
        flags[] = true;
        for (i = 0; i < flags.length; i++)
        {   if (flags[i])
            {   prime = i + i + 3;
                k = i + prime;
                while (k < flags.length)
                {
                    flags[k] = false;
                    k += prime;
                }
                count += 1;
            }
        }
    }
    printf ("\n%d primes", count);
    return 0;
}

Eratosthenes Sieve in Mango

literal 
  total_iter is 10;
  prime_max is 8192;

type prime_number of ordinal{prime_max} having overflow checked;

variable flags of prime_number mask;

program sieve is
  declare count of cardinal/32;

  print total_iter, " iterations.", eol;

  foreach iter in 1 to total_iter do
    declare k of cardinal/32;

    set flags;

    foreach i in <range, prime_number> where i > 0 and flags[i] do
       let prime = i + i + 3;
       assign i + prime into k;
       while k < prime_max do
          reset flags[k];
          incr k with prime;   

       incr count when iter == total_iter;
  
  print eol, count, " primes", eol;

Hello World in D

int main(char[][] args)
{
    printf("hello world\n");
    printf("args.length = %d\n", args.length);
    for (int i = 0; i < args.length; i++)
        printf("args[%d] = '%s'\n", i, (char *)args[i]);
    return 0;
}

Hello World in Mango

program hello with args of args_string is
  print "hello world", eol;
  print "# args = ", args size, eol;

  foreach a in args over i do
    print "args[", i, "] = '", a, "'", eol;

PI calculation in D

import std.c.stdio;
import std.c.stdlib;
import std.c.time;

const int MAXPRC = 4000;

byte p[MAXPRC];
byte t[MAXPRC];
int q;

int main(char[][] args)
{
	int startime, endtime;
	int i;

	if (args.length == 2) {
		sscanf(&args[1][0],"%d",&q);
	} else {
		printf("Usage: pi [precision]\n");
		exit(55);
	}

	if (q >= MAXPRC)
	{
		printf("Precision exceeds maximum of %d\n", MAXPRC);
		exit(66);
	}

	/* compute pi */

	std.c.time.time(&startime);
	arctan(2);
	arctan(3);
	mul4();
	std.c.time.time(&endtime);

	/* print pi */

	printf("pi = %d.",p[0]);
	for (i = 1; i <= q; i++)
		printf("%d",p[i]);
	printf("\n");
	printf("%ld seconds to compute %d digits of pi\n",endtime-startime,q);

	return 0;
}

void arctan(int s)
{
	int n;

	t[0] = 1;
	div(s);			/* t[] = 1/s */
	add();
	n = 1;
	do {
		mul(n);
		div(s * s);
		div(n += 2);
		if (((n-1) / 2) % 2 == 0)
			add();
		else
			sub();
	} while (!tiszero());
}

void add()
{
	int j;

	for (j = q; j >= 0; j--)
	{
		if (t[j] + p[j] > 9) {
			p[j] += t[j] - 10;
			p[j-1] += 1;
		} else
			p[j] += t[j];
	}
}

void sub()
{
	int j;

	for (j = q; j >= 0; j--)
		if (p[j] < t[j]) {
			p[j] -= t[j] - 10;
			p[j-1] -= 1;
		} else
			p[j] -= t[j];
}

void mul(int multiplier)
{
	int b;
	int i;
	int carry = 0, digit = 0;

	for (i = q; i >= 0; i--) {
		b = (t[i] * multiplier + carry);
		digit = b % 10;
		carry = b / 10;
		t[i] = digit;
	}
}

/* t[] /= l */

void div(int divisor)
{
	int i, b;
	int quotient, remainder = 0;

	for (i = 0; i <= q; i++) {
		b = (10 * remainder + t[i]);
		quotient = b / divisor;
		remainder = b % divisor;
		t[i] = quotient;
	}
}

void div4()
{
	int i, c, d = 0;

	for (i = 0; i <= q; i++) {
		c = (10 * d + p[i]) / 4;
		d = (10 * d + p[i]) % 4;
		p[i] = c;
	}
}

void mul4()
{
	int i, c, d;

	d = c = 0;

	for (i = q; i >= 0; i--) {
		d = (p[i] * 4 + c) % 10;
		c = (p[i] * 4 + c) / 10;
		p[i] = d;
	}
}

int tiszero()
{
	int k;

	for (k = 0; k <= q; k++)
		if (t[k] != 0)
			return false;
	return true;
}




PI calculation in Mango

import std/time;

literal maxprc is 4000;

program pi with args of args_string do
  declare 
     n of decimal {3:maxprc};
     q of cardinal/32;

  if args size == 2 then
   perform
     eval args[1] with scan_value into q;
   else
     print "Usage: pi [precision]", eol;
     quit;

  if q >= maxprc then
    print "Precision exceeds maximum of ", maxprc, eol;
    quit;
  
  **
  ** compute pi
  **

  call std::time into &start;
  assign 4 * (arctan(1/2) + arctan(1/3)) into n;
  call std::time into &end;

  **
  ** print pi
  **

  print "pi = ", [precision=q] -> n, eol;

  let time = end - start;
  print time, " seconds to compute ", q, " digits of pi", eol;

8 Queens Problem in C++

#include <vector>
#include <iostream>

class Queens
{
    int size;
    std::vector<int> queens;

    bool attacks(int x0, int y0, int x1, int y1)
    {
        return x0==x1 || y0==y1 || abs(x0-x1)==abs(y0-y1);
    }

    bool solve(int x=0)
    {
        if(x==size)
        {
            printSolution();
            return true;
        }

        for(int y=0; y<size; ++y)
        {
            bool attacked=false;

            // Test that the queen does not attack position (x,y) with any previous queens
            for(int x0=0; x0<x; ++x0)
                if(attacks(x0,queens[x0],x,y)) { attacked=true; break; }

           if(!attacked)
            {
                queens[x]=y;
                if(solve(x+1)) return true;
            }
        }
        return false;
    }

    void printSolution()
    {
        for(int y=0; y<size; ++y)
        {
            for(int x=0; x<size; ++x)
                std::cout << (queens[y]==x ? 'Q' : '_');
            std::cout << std::endl;
        }
    }

public:
    Queens(int s) : size(s), queens(size)
    {
        solve();
    }
};


int main(int argc, char **argv)
{
    int size = argc==2 ? atoi(argv[1]) : 8;

    Queens q(size);

    return 0;
}

8 Queens Problem in Mango

import std/args, ascii/util;

type point of integer coordinate {x,y};

function attacks with p1 of point, p2 of point yielding logical/boolean is
  p1.x == p2.x or p1.y == p2.y or |p1.x - p2.x| == |p1.y - p2.y|;

procedure solve with mx of integer, queens of integer string yielding logical/boolean is
  let size = queens size;

  return true when mx == size;  

  foreach y in 1 to size where not (some x in 1 to mx where attacks([x, queens[x]], [mx, y])) do
    assign y into queens[mx];
    eval mx+1, queens with solve into &s;
    return true when s?;

  return false;

procedure print_solution with queens of integer string is
  foreach [pt of point] in [0,0] to [size, size] do
    print "Q" when queens[pt.y] == pt.x else "_";
    print eol when pt.x == size;

program queens with args of args_string is
  eval args[1] with ascii_to_integer into &size 
    when args size == 2 else 8;
  alloc queens of integer string upto size;  
  eval 1, queens with solve into nil;
  call print_solution with queens;

Bubble Sort in C++

#include <iostream>
#include <vector>

int main(void)
{
    std::vector<int> vec;

    for (int count = 0, tmp; count < 25; count++) {
        std::cout << '>' << std::flush;
        std::cin >> tmp;
        if (tmp == 0)
          break;
        vec.push_back(tmp);
    }

    bool swapped(false);
    do {
        swapped = false;
        for (unsigned i(0); i < vec.size() - 1; ++i)
            if (vec[i] > vec[i+1])
              std::swap(vec[i], vec[i+1]), swapped = true;
    } while (swapped);

    for (unsigned i(0); i < vec.size(); ++i)
      std::cout << vec[i] << std::endl;
}

Bubble Sort in Mango

import std/io;

program sort is
  declare list of integer list;

  repeat
    read [x of integer] from stdin;
    exit when x == 0;
    add x into list;    

  repeat
    declare x of logical/boolean;

    foreach i in 1 to list size - 1 where list[i] > list[i+1] do
      swap list[i] with list[i+1];
      set x;

    exit when x == false;

  foreach x in list do
    print x, eol;


Primes in C

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

struct intlist {
    int *a;
    size_t len;
    size_t cap;
};

int intlist_add(struct intlist *p, int next)
{
    if (p->len >= p->cap) {
        void *t;
        p->cap = p->cap*2 + 5;
        t = realloc(p->a, p->cap * sizeof *p->a);
        if (t == NULL)
          exit(EXIT_FAILURE);
        p->a = t;
    }
    p->a[p->len++] = next;
    return next;
}


int checkPrime(int i, struct intlist list)
{
    if (list.len == 0) return 1;
    if (i % list.a[0]) {
        struct intlist list2 = {list.a+1, list.len-1, list.cap};
        return checkPrime(i, list2);
    }
    return 0;
}


int next_prime(int go)
{
    static struct intlist list = {0};
    if (go == 0) {
        free(list.a);
        return 0;
    }
    if (list.a == NULL)
      return intlist_add(&list, 2);
    else {
        int first = list.a[list.len - 1];
        int i;
        for (i = first+1; !checkPrime(i, list); ++i)
          ;
        return intlist_add(&list, i);
    }
}


int main(void)
{
    int i;
    for (i=0; i < 1000; ++i)
      printf("%d ", next_prime(1));
    printf("\n");
    next_prime(0);
    return 0;
}

Primes in Mango

module primes;

import std/program, ascii/utils;

procedure find_primes n of integer, primes of (integer list)& do
   exit when n == 0;

   add 2 into primes;
   declare z of integer where z = 3;

   while primes size < n do
     while some x in primes where z % x == 0 do
       incr z;
     add z into primes;

program primes with args of args_string is
  eval args[1] with ascii_to_integer into &n 
    when args size == 2 else 1000;

  declare primes of integer list;
  
  call find_primes with n, primes;

  foreach i in primes do
    print i, " ";

  print eol;