This source file includes following definitions.
- potion_source
 
- potion_source_size
 
- potion_source_name
 
- potion_source_file
 
- potion_source_line
 
- potion_source_string
 
- potion_source_loc
 
- potion_source_init
 
#include <stdio.h>
#include <stdlib.h>
#include "p2.h"
#include "internal.h"
#include "ast.h"
const char *potion_ast_names[] = {
  "code", "value", "assign", "not", "or", "and", "cmp", "eq", "neq",
  "gt", "gte", "lt", "lte", "pipe", "caret", "amp", "wavy", "bitl",
  "bitr", "plus", "minus", "inc", "times", "div", "rem", "pow",
  "msg", "path", "query", "pathq", "expr", "list", "block", "lick",
  "proto", "debug"
};
const int potion_ast_sizes[] = {
  1, 3, 2, 1, 2, 2, 2, 2, 2,
  2, 2, 2, 2, 2, 2, 2, 1, 2,
  2, 2, 2, 2, 2, 2, 2, 2,
  3, 1, 1, 1, 1, 1, 1, 3,
  2, 3
};
PN potion_source(Potion *P, u8 p, PN a, PN b, PN c, int lineno, PN line) {
  int size = potion_ast_sizes[p];
  
  vPN(Source) t = PN_ALLOC_N(PN_TSOURCE, struct PNSource, 0 * sizeof(PN));
  t->part = (enum PN_AST)p;
  t->loc.fileno = P->fileno; 
  t->loc.lineno = lineno;
  t->line = line;
#if 1
  switch (size) {
  case 3: t->a[2] = PN_SRC(c);
  case 2: t->a[1] = PN_SRC(b);
  case 1: t->a[0] = PN_SRC(a); break;
  default: potion_fatal("invalid AST type");
  }
#else
  switch (size) {
  case 3: t->a[0] = PN_SRC(a); t->a[1] = PN_SRC(b); t->a[2] = PN_SRC(c); break;
  case 2: t->a[0] = PN_SRC(a); t->a[1] = PN_SRC(b); t->a[2] = 0; break;
  case 1: t->a[0] = PN_SRC(a); t->a[1] = t->a[2] = 0; break;
  default: potion_fatal("invalid AST type");
  }
#endif
  return (PN)t;
}
PN potion_source_size(Potion *P, PN cl, PN self) {
  vPN(Source) t = (struct PNSource *)potion_fwd(self);
  return PN_NUM(potion_ast_sizes[t->part]);
}
PN potion_source_name(Potion *P, PN cl, PN self) {
  vPN(Source) t = (struct PNSource *)potion_fwd(self);
  return potion_str(P, potion_ast_names[t->part]);
}
PN potion_source_file(Potion *P, PN cl, PN self) {
  vPN(Source) t = (struct PNSource *)potion_fwd(self);
  return PN_TUPLE_AT(pn_filenames, t->loc.fileno);
}
PN potion_source_line(Potion *P, PN cl, PN self) {
  vPN(Source) t = (struct PNSource *)potion_fwd(self);
  return PN_NUM(t->loc.lineno);
}
PN potion_source_string(Potion *P, PN cl, PN self) {
  int i, n, cut = 0;
  vPN(Source) t = (struct PNSource *)potion_fwd(self);
  PN out = potion_byte_str(P, potion_ast_names[t->part]);
  int lineno = t->loc.lineno;
  n = potion_ast_sizes[t->part];
  for (i = 0; i < n; i++) {
    pn_printf(P, out, " ");
    if (i == 0 && n > 1) pn_printf(P, out, "(");
    else if (i > 0) {
      if (!t->a[i]) { 
        if (!cut) cut = PN_STR_LEN(out);
      }
      else cut = 0;
    }
    if (PN_IS_STR(t->a[i])) {
      pn_printf(P, out, "\"");
      potion_bytes_obj_string(P, out, (PN)t->a[i]);
      pn_printf(P, out, "\"");
    } else {
      potion_bytes_obj_string(P, out, (PN)t->a[i]);
    }
    if ((PN_TYPE(t->a[i]) == PN_TSOURCE) && (t->a[i]->loc.lineno > lineno)) {
      pn_printf(P, out, "\n");
      lineno = t->a[i]->loc.lineno;
    }
    if (i == n - 1 && n > 1) {
      if (cut > 0) {
        vPN(Bytes) b = (struct PNBytes *)potion_fwd(out);
        
        if (cut < b->len) {
          b->len = cut - 1;
          if (b->chars[cut-1] == ' ')
            b->chars[cut-1] = '\0';
          else
            b->chars[cut] = '\0';
        }
      }
      pn_printf(P, out, ")");
    }
  }
  return PN_STR_B(out);
}
PN potion_source_loc(Potion *P, PN cl, PN self) {
  PN out = potion_byte_str(P, "");
  pn_printf(P, out, "%s:%ld",
            PN_STR_PTR(potion_source_file(P, cl, self)),
            PN_INT(potion_source_line(P, cl, self)));
  return PN_STR_B(out);
}
void potion_source_init(Potion *P) {
  PN src_vt = PN_VTABLE(PN_TSOURCE);
  potion_method(src_vt, "name", potion_source_name, 0);
  potion_method(src_vt, "string", potion_source_string, 0);
  potion_method(src_vt, "size", potion_source_size, 0);
  potion_method(src_vt, "file", potion_source_file, 0);
  potion_method(src_vt, "line", potion_source_line, 0);
}